struct node { node(); //node(const node&); //#1 //node(node&&); //#2 virtual //#3 ~node (); node* volatile //#4 next; }; int main() { node m(node()); //#5 node n=node(); //#6 }
当使用gcc-4.6.1编译时,会产生以下错误:
g++ -g --std=c++0x -c -o node.o node.cc node.cc: In constructor node::node(node&&): node.cc:3:8: error: expression node::next has side-effects node.cc: In function int main(): node.cc:18:14: note: synthesized method node::node(node&&) first required here
据了解,编译器无法在第6行上创建默认移动或复制构造函数,如果我取消注释行#1或#2,它会编译好,这是很清楚的.代码编译没有c 0x选项,所以错误与默认移动构造函数相关.
但是,节点类中什么阻止默认移动构造函数被创建?如果我注释任何行#3或#4(即使析构函数非虚拟或使数据成员非易失性)它再次编译,这两个组合是否使其不编译?
另一个难题,第5行不会导致编译错误,与第6行有什么不同?
这是否具体针对gcc?或gcc-4.6.1?
解决方法
[C++11: 12.8/9]:
If the definition of a classX
does not explicitly declare a move constructor,one will be implicitly declared as defaulted if and only if
X
does not have a user-declared copy constructor,X
does not have a user-declared copy assignment operator,X
does not have a user-declared move assignment operator,X
does not have a user-declared destructor,and- the move constructor would not be implicitly defined as deleted.
[ Note: When the move constructor is not implicitly declared or explicitly supplied,expressions that otherwise
would have invoked the move constructor may instead invoke a copy constructor. —end note ]
这就是为什么你的#3打破了综合.
另外it’s far from clear是volatile types (including your node* volatile
) are trivially copyable;可以得出结论,it is implementation-defined whether they are or not,在你的情况下,似乎它们不是.
至少,GCC made it stop working quite deliberately在v4.7中,有一个提案到v4.6.1,我只能假定继续前进…
所以,给出如下:
[C++11: 12.8/11]:
An implicitly-declared copy/move constructor is an inline public member of its class. A defaulted copy/move constructor for a classX
is defined as deleted (8.4.3) ifX
has:
- a variant member with a non-trivial corresponding constructor and
X
is a union-like class,
a non-static data member of class typeM
(or array thereof) that cannot be copied/moved because overload resolution (13.3),as applied toM
’s corresponding constructor,results in an ambiguity or a function that is deleted or inaccessible from the defaulted constructor,- a direct or virtual base class
B
that cannot be copied/moved because overload resolution (13.3),as applied toB
’s corresponding constructor,- any direct or virtual base class or non-static data member of a type with a destructor that is deleted or inaccessible from the defaulted constructor,
- for the copy constructor,a non-static data member of rvalue reference type,or
- for the move constructor,a non-static data member or direct or virtual base class with a type that does not have a move constructor and is not trivially copyable.
…这就是为什么你的#4也是打破综合性,独立于#3.
对于#5,实际上并不是一个节点的声明,而是一个名为m的函数的声明 – 这就是为什么它不再现与节点构造相关的症状(这被称为Most Vexing Parse).