复制/移动省略与显式删除的复制/移动构造函数
Copy/move elision versus explicitly deleted copy/move constructors
我想知道复制/移动省略何时应用(或允许应用)显式delete
d复制/移动构造函数和非delete
d复制/移构造函数。具体情况如下:
-
显式
delete
d复制ctor或移动ctor是否可以被消除?通过跳过delete
d复制ctor和/或delete
d移动ctor,是否允许从另一个相同类型的对象或临时对象构造对象的尝试成功?以下是VC12中发生的情况(我不确定是否有禁用复制/移动省略的选项):
#include <iostream> struct Foo { Foo() { std::cout << "default ctorn"; } Foo(Foo const&) = delete; Foo(Foo&&) = delete; }; int main() { // ----Output------ Foo{ Foo() }; // "default ctor" Foo f; // "default ctor" Foo{ std::move(f) }; // error C2280: 'Foo::Foo(Foo &&)' : attempting to reference a deleted function Foo{ f }; // error C2280: 'Foo::Foo(const Foo &)' : attempting to reference a deleted function }
即使IntelliSense抱怨
Foo{ Foo() };
:Error: function “Foo::Foo(Foo &&)” ... cannot be referenced – it is a deleted function
,编译器也没有抱怨,所以这一行仍然在编译。 -
为什么
Foo{ Foo() };
有效,而Foo{ std::move(f) };
无效?如果一个调用省略了move ctor,那么另一个不应该吗? -
为什么
Foo{ Foo() };
有效,而Foo{ f };
无效?这种选择性看起来是任意的。这种右值引用相对于常量引用的任意偏好(反之亦然)似乎不适用于非ctor方法;其中,在调用中,如果delete
d重载的重载分辨率优先级高于非delete
d重载,则delete
d重载会阻塞非delete
d重载,从而导致编译器错误:struct Bar { void g(int const&) {} void g(int&&) = delete; }; //… Bar b; b.g(2); //error C2280: 'void Bar::g(int &&)' : attempting to reference a deleted function // ^ Would have compiled had function `g(int&&)` been commented out.
根据该逻辑,当参数不是临时的时,
delete
dFoo(Foo&&)
不应该阻止对Foo(Foo const&)
的调用;在这种情况下,CCD_ 19将具有比CCD_ 20更低的过载解决优先级。 -
我在g++4.8中尝试了相同的
Foo
示例,其中禁用了复制省略(通过标志-fno-elide-constructors
),并再次启用了它。两个g++试验都给出:error: use of deleted function 'Foo::Foo(Foo&&)'
用于Foo{ Foo() };
和error: use of deleted function 'Foo::Foo(const Foo&)'
用于Foo{ f };
哪个编译器是正确的?
Ms VC++有一个非常古老的众所周知的bug。来自C++标准
[注意:必须执行此两阶段过载解决方案而不管是否会发生拷贝省略。它决定了如果未执行省略,则要调用的构造函数,并且构造函数必须是可访问的,即使调用被取消--尾注]
- C++17复制构造函数,在std::unordereded_map上进行深度复制
- 为什么在C++中使用私有复制构造函数与删除复制构造函数
- 当从函数参数中的临时值调用复制构造函数时
- 如果有一个模板构造函数只有一个泛型参数,为什么我必须有一个复制构造函数
- 为什么需要复制构造函数,在哪些情况下它们非常有用
- 使用仅使用一次的变量调用的复制构造函数.这可能是通过调用move构造函数进行编译器优化的情况吗
- 为什么类中的ostringstream类型的成员会导致";调用隐含删除复制构造函数";错误
- 复制构造函数、赋值运算符C++
- std::ofstream 作为类成员删除复制构造函数?
- 复制构造函数C++无法正确复制指针
- 关于复制构造函数的一个棘手问题
- 为什么调用复制构造函数而不是移动构造函数?
- 填充上编译器生成的复制构造函数之间的不一致
- C++ 对象指针数组的复制构造函数
- C++ 基本 CTOR 说明 - 为什么不调用赋值/复制构造函数
- 防止在复制构造函数中隐式调用基构造函数
- 为用户定义的类正确调用复制构造函数/赋值运算符
- 具有已删除移动和复制构造函数的类的就地构造
- 复制构造函数隐式转换问题
- 复制构造函数中的递归调用