Kno*_*abe 8 c++ copy-constructor move-semantics c++11
当类显式声明复制操作(即复制构造函数或复制赋值运算符)时,不会为该类声明移动操作.但是当一个类显式声明一个移动操作时,复制操作被声明为已删除.为什么存在这种不对称?为什么不指定如果声明移动操作,则不会声明复制操作?据我所知,不存在任何行为差异,也不需要对移动和复制操作进行不对称处理.
[对于喜欢引用该标准的人,在12.8/9和12.8/20中指定缺少具有复制操作声明的类的移动操作声明,并且具有移动操作声明的类的已删除复制操作在12.8 /中指定7和12.8/18.]
当一个类被移动但是由于没有声明移动构造函数时,编译器会回退到复制构造函数.在相同的情况下,如果将移动构造函数声明为已删除,则程序将是格式错误的.因此,如果将移动构造函数隐式声明为已删除,则许多涉及现有C++ 11之前类的合理代码将无法编译.像myVector.push_back(MyClass())
这解释了为什么在定义复制构造函数时不能隐式声明移动构造函数.这就留下了为什么在定义移动构造函数时隐式声明复制构造函数被删除的问题.
我不知道委员会的确切动机,但我有一个猜测.如果将移动构造函数添加到现有的C++ 03样式类中,则删除(先前隐式定义的)复制构造函数,那么使用此类的现有代码可能会以微妙的方式改变含义,因为重载决策选择了过去的意外重载拒绝接受更糟糕的比赛
考虑:
struct C {
C(int) {}
operator int() { return 42; }
};
C a(1);
C b(a); // (1)
Run Code Online (Sandbox Code Playgroud)
这是一个遗留的C++ 03类.(1)调用(隐式定义的)复制构造函数.C b((int)a);也是可行的,但是更糟糕的比赛.
想象一下,无论出于何种原因,我决定在这个类中添加一个显式移动构造函数.如果移动构造函数的存在是为了抑制复制构造函数的隐式声明,那么(1)中看似无关的代码片段仍然会编译,但会默默地改变它的含义:它现在会调用operator int()和C(int).那会很糟糕.
另一方面,如果复制构造函数被隐式声明为已删除,则(1)将无法编译,提醒我该问题.我会检查一下情况,然后决定是否还需要一个默认的复制构造函数; 如果是的话,我会补充一下C(const C&)=default;