运算符 + 需要移动构造函数
operator + need Move Constructors
我无法编译附加的项目,因为我删除了移动构造函数。
这是预期的行为吗?如果编译器不使用移动构造函数,为什么还需要它?
Windows-Visual Studio 2015 14.0.25431.01 更新3
#include <string>
#include <sstream>
#include <vector>
class poo {
public:
poo() = default;
poo(poo&&) = delete; //deleted function
virtual ~poo() = default;
poo operator +(const poo &a) const {
poo to_return;
to_return._s += a._s;
return to_return;
//moveconstructors.cpp(14): error C2280: 'poo::poo(poo &&)': attempting to reference a deleted function
}
private:
std::string _s;
};
int main(int, char **) {
poo a;
return 0;
}
编辑 1: 添加"便便(常量便便&)=默认值;"后会发生相同的结果;
编辑2: Windows-Visual Studio 2019 16.1.0 Preview 2.0 也会发生相同的结果
。编辑3: 添加/修改后发生相同的结果
poo(const std::string &s) : _s(s) {
}
poo operator +(const poo& a) const {
return poo(_s + a._s);
}
编辑4:它适用于vs2019和/std:c ++ 17
poo(poo&&) = delete;
是的,此行禁用移动构造函数,但它也会删除复制构造函数。
来自class.copy.ctor:
如果类定义未显式声明复制构造函数,则隐式声明非显式构造函数。 如果类定义声明了移动构造函数或移动赋值运算符,则隐式声明的副本 构造函数定义为已删除;。
现在,如果标准保证命名返回值优化 (NRVO),那么这一切都没什么大不了的,因为编译器可以看到您的operator+
具有单个局部变量的返回。在这种情况下,我们不需要复制或移动构造函数;poo
实例将被创建并通过引用("在引擎盖下")传递给 FN。
请注意,在 C++17 中,您可以使用保证复制 (RVO) 来解决此问题:
poo(std::string s) : _s(std::move(s)){}
poo operator +(const poo &a) const {
return poo(_s + a._s);
}
演示
但是,即使在 C++20 中,命名返回值优化也尚未得到保证。允许实现改用移动操作。
[class.copy.elision] 指出:
在以下复制初始化上下文中,可以使用移动操作代替复制操作:
- 如果return语句中的表达式是一个(可能是括号)id-表达式,该表达式命名一个对象,并在最内层封闭函数或lambda 表达式
此处允许省略优化 (NRVO),但对象在语义上仍必须是可复制/可移动的;通过删除移动构造函数,您还删除了复制构造函数,因此这两个操作都无效,程序格式不正确。
您可以重新添加复制 ctor:
poo(const poo&) = default;
(而且,即使您使用的是 C++17,其保证省略也不适用于左值。
- 为什么不调用移动构造函数?(默认情况下只有构造器,没有别的)
- std::vector::p ush_back() 不会在 MSVC 上编译具有已删除移动构造函数的对象
- 仅包含可移动 std::map 的类的移动构造函数不起作用
- 为什么调用复制构造函数而不是移动构造函数?
- 基类中的默认析构函数禁用子类中的移动构造函数(如果有成员)
- 从具有按值捕获的 lambda 移动构造 std::函数时,移动构造函数调用两次
- 移动构造函数和右值引用
- 为什么 std::memmove 中联合的默认非平凡移动构造函数C++?
- 具有专用化的模板类中的可靠条件复制和移动构造函数
- C++:为什么不调用移动构造函数?
- 移动构造函数永远不会被调用
- C++:关于使用 Stroustrup 示例移动构造函数/赋值的问题
- 运算符+ 的规范实现涉及额外的移动构造函数
- C ++为什么在移动构造函数中需要移动/前进
- 为什么在删除"移动构造函数"时使用"复制构造函数"?
- 为什么这里不调用移动构造函数?
- 隐式移动构造函数
- 如何为具有私有成员的派生类实现移动构造函数
- 为什么不调用移动构造函数
- 是否可以避免在以下代码中复制/移动构造函数的需要?