为什么在返回时将复制构造函数而不是移动构造函数
Why is the copy constructor called instead of the move constructor when returning?
假设我的类MyClass
具有正确的移动构造函数,并且删除了复制构造函数。现在我要返回这样的课程:
MyClass func()
{
return MyClass();
}
在这种情况下
现在说MyClass
具有<<
操作员的实现:
MyClass& operator<<(MyClass& target, const int& source)
{
target.add(source);
return target;
}
当我更改上述代码时:
MyClass func()
{
return MyClass() << 5;
}
我遇到了编译器错误,因此无法访问复制构造函数,因为它已删除。但是为什么在这种情况下完全使用复制构造函数?
现在,我正在通过这样的lvalue返回此类:
MyClass func() { return MyClass(); }
no,返回的表达式为 xvalue (一种rvalue(,用于初始化返回结果的结果(由于C 17,情况有些复杂,但是这仍然是它的要旨;此外,您在C 11(。
在这种情况下
确实;rvalue将初始化rvalue参考,因此整个内容都可以匹配移动构造函数。
当我更改上述代码时:
&hellip;现在的表达式为MyClass() << 5
,它具有MyClass&
类型。这从来都不是rvalue。这是一个lvalue。这是指现有对象的表达式。
因此,如果没有明确的std::move
,则可以将其用于 copy-initialise 结果。而且,由于您的复制构造函数已被删除,因此无法使用。
我完全感到惊讶的是示例编译,因为临时性不能用来初始化lvalue参考(您的操作员的第一个参数(,尽管已知某些工具链(MSV(接受了它作为扩展。bk_hr>
然后将返回
std::move(MyClass() << 5);
工作?
是的,我相信。
但是,这很奇怪,并使读者进行了仔细检查,以确保没有悬而未决的参考。这表明有一种更好的方法可以实现更清晰的代码:
MyClass func()
{
MyClass m;
m << 5;
return m;
}
现在,您仍然在没有任何奇怪的滑稽动作的情况下移动(因为这是return
局部变量时的特殊规则(。而且,作为奖励,<<
呼叫完全符合标准。
您的操作员返回MyClass&
。因此,您正在返回一个lvalue,而不是可以自动移动的rvalue。
您可以通过依靠NRVO的标准保证来避免副本。
MyClass func()
{
MyClass m;
m << 5;
return m;
}
这将完全列出对象,或者移动它。所有这些都因为它是函数本地对象。
另一个选项,在您尝试在rvalue上调用 operator<<
时,是在rvalue参考文献中提供过载。
MyClass&& operator<<(MyClass&& target, int i) {
target << i; // Reuse the operator you have, here target is an lvalue
return std::move(target);
}
将使MyClass() << 5
本身形成良好(请参阅另一个答案(,并返回可以构造返回对象的XVALUE。虽然通常看不到operator<<
的超载。
您的operator<<
将其第一个参数作为非const参考。您不能将非企业引用绑定到临时性。但是MyClass()
将新创建的实例作为临时返回。
另外,当func
返回值时,operator<<
返回参考。那么,除了返回副本外,还能做什么?
- 为什么不调用移动构造函数?(默认情况下只有构造器,没有别的)
- std::vector::p ush_back() 不会在 MSVC 上编译具有已删除移动构造函数的对象
- 仅包含可移动 std::map 的类的移动构造函数不起作用
- 为什么调用复制构造函数而不是移动构造函数?
- 基类中的默认析构函数禁用子类中的移动构造函数(如果有成员)
- 从具有按值捕获的 lambda 移动构造 std::函数时,移动构造函数调用两次
- 具有已删除移动和复制构造函数的类的就地构造
- 移动构造函数和右值引用
- 使用移动调用对等构造函数unique_ptr默认构造函数
- 为什么 std::memmove 中联合的默认非平凡移动构造函数C++?
- 具有专用化的模板类中的可靠条件复制和移动构造函数
- 构造函数采用std::string_view与std::string并移动
- C++:为什么不调用移动构造函数?
- 了解构造函数在移动、复制、赋值语义中的行为
- 没有移动的构造函数移动课程
- 引用绑定和复制构造函数/移动构造函数
- 构造函数移动
- C++ 向量实现 - 移动构造函数 - 移动与前进
- 我真的必须取消移动构造函数/移动结构中的所有成员还是只是指针
- 将类(没有默认构造函数)移动到另一个类的move构造函数中