use*_*766 10 c++ g++ move-constructor c++11
看下面的代码:
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
}
Run Code Online (Sandbox Code Playgroud)
使用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
Run Code Online (Sandbox Code Playgroud)
据我所知,编译器无法在第6行创建默认移动或复制构造函数,如果我取消注释第1行或第2行它编译正常,这很清楚.代码在没有c ++ 0x选项的情况下编译正常,因此错误与默认移动构造函数有关.
但是,节点类中的内容会阻止创建默认移动构造函数吗?如果我评论任何第3行或第4行(即使析构函数非虚拟或使数据成员非易失性)它再次编译,那么这两者的组合是否使它不能编译?
另一个难题,第5行不会导致编译错误,与第6行有什么不同?它是否特定于gcc?还是gcc-4.6.1?
Lig*_*ica 12
[C++11: 12.8/9]:
如果类的定义X
没有显式声明一个移动构造函数,那么当且仅当一个类的定义被隐式声明为默认值时
X
没有用户声明的复制构造函数,X
没有用户声明的复制赋值运算符,X
没有用户声明的移动赋值运算符,X
没有用户声明的析构函数,和- 移动构造函数不会被隐式定义为已删除.
[ 注意:当未隐式声明或显式提供移动构造函数时,否则将调用移动构造函数的表达式可能会调用复制构造函数. - 尾注]
这就是你的#3打破综合的原因.
此外,这是很不明朗的是挥发性的类型(包括你node* volatile
)是平凡可复制 ; 可以得出结论,它是否是实现定义的,并且在您的情况下,似乎它们不是.
至少,海湾合作委员会让它在第4.7节中非常刻意地停止了工作,提出了向后推进到v4.6.1的建议,我只能假设继续......
所以,鉴于以下内容:
[C++11: 12.8/11]:
隐式声明的复制/移动构造函数是其类的内联公共成员.如果具有以下内容,则将类的默认复制/移动构造函数X
定义为已删除(8.4.3)X
:
- 用非平凡相应构造的变体构件和
X
是联合状类,类类型的非静态数据成员M
(或其阵列),其不能被复制/移动,因为重载解析(13.3),作为施加到M
的相应的构造函数,导致歧义或从默认构造函数中删除或无法访问的函数,- 一个
B
无法复制/移动的直接或虚拟基类,因为重载解析(13.3),应用于B
相应的构造函数,会导致歧义或从默认构造函数中删除或无法访问的函数,- 任何直接或虚拟基类或具有析构函数的非静态数据成员,该析构函数已从默认构造函数中删除或无法访问,
- 对于复制构造函数,rvalue引用类型的非静态数据成员,或
- 对于移动构造函数,一个非静态数据成员或直接或虚拟基类,其类型没有移动构造函数,并且不是简单的可复制.
......这就是为什么你的#4正在打破合成,独立于#3.
至于#5,它实际上并不是一个声明node
,而是一个被称为函数的声明m
- 这就是为什么它不能再现与构造a相关的症状node
(这被称为最令人烦恼的解析).
归档时间: |
|
查看次数: |
906 次 |
最近记录: |