为简单结构定义哪个复制/移动构造函数/运算符
Which copy/move constructor/operator to define for simple structures?
我的程序使用一个简单的结构Rect
,它被定义为
struct Rect {
int x1, y1, x2, y2;
Rect()
: x1(0), y1(0), x2(0), y2(0) { }
Rect(int x1, int y1, int x2, int y2)
: x1(x1), y1(y1), x2(x2), y2(y2) { }
};
我应该定义一个复制/移动构造函数或赋值运算符吗?还是可以依靠编译器自动生成它们?这个问题是在速度和使用原因的背景下提出的(例如,移动构造函数可以影响程序执行速度)。
构造函数和运算符是非常重复的工作,所以如果我能依靠编译器自动生成它们,那就太好了。
Rect(const Rect& r)
: x1(r.x1), y1(r.y1), x2(r.x2), y2(r.y2) { }
Rect(Rect&& r)
: x1(r.x1), y1(r.y1), x2(r.x2), y2(r.y2) { }
Rect& operator = (const Rect& r) {
x1 = r.x1;
y1 = r.y1;
x2 = r.x2;
y2 = r.y2;
}
Q1:你能依靠编译器自动生成这些吗
是的(在你的例子中)。请参阅C++11标准(第12条),或文章"隐式移动不会成功!"!(结尾处的图表很漂亮)。综上所述(并简化),以下所有特殊成员函数都将自动生成(隐式声明并定义为默认值):
- 析构函数–因为您没有声明它
- 复制构造函数–因为您没有声明它,也没有声明任何MC和MAO
- 复制分配运算符–因为您没有声明它,也没有声明任何MC和MAO
- 移动构造函数–因为您既没有声明它,也没有声明D、CC、CAO和MAO中的任何一个
- 移动分配运算符–因为您既没有声明它,也没有声明D、CC、CAO和MC中的任何一个
(我使用了丑陋的首字母缩写,只是为了让列表项各保留一行。)除了上面的"因为"之外,对于除析构函数之外的所有项,还有一个额外的约束,即生成的默认值必须有意义,即所有数据成员都必须是可复制的(对于CC和CAO)或可移动的(对于MC和MAO)。(实际上,确切的规则有点复杂,但我不想在这里重新表述标准。)
Q2:自动生成的函数是否正确
是的(在你的例子中)。所有的数据成员(这里是普通的int
)都有正确的复制/移动语义(他们的复制/移动构造函数和赋值运算符做了正确的事情,而那些为Rect
自动生成的将调用它们)。
Q3:不管怎样,你应该手动定义它们吗
我认为它(在您的示例中)没有优势,也没有潜在的问题(如在您的实例中,请参阅注释)。
您可以在编译器上中继,因为您的数据成员是内置类型,因此可以通过成员复制创建对象的副本。如果您既没有定义复制/移动构造函数,也没有定义赋值运算符,则会出现这种情况。如果您有一个指针作为数据成员,则可能需要它们。
您不需要编写显式复制构造函数,因为您的结构Rect的成员都是c++内置类型,所以编译器会生成一个逐位复制构造函数。在你的代码中,我认为你可以完全依赖你的编译器。
如果您出于某些原因想要详细说明,您可以将它们声明为默认的自文档,如下所示:
struct Rect {
int x1, y1, x2, y2;
Rect () : Rect( 0, 0, 0, 0 ) { }
Rect ( int x1, int y1, int x2, int y2 )
: x1(x1), y1(y1), x2(x2), y2(y2) { }
// Rect is Copy/Move Constructible and Assignable
Rect( Rect const & ) = default;
Rect( Rect && ) = default;
Rect& operator= ( Rect const & ) = default;
Rect& operator= ( Rect && ) = default;
};
还注意到,由于委托构造函数
- 为什么不调用移动构造函数?(默认情况下只有构造器,没有别的)
- std::vector::p ush_back() 不会在 MSVC 上编译具有已删除移动构造函数的对象
- 仅包含可移动 std::map 的类的移动构造函数不起作用
- 为什么调用复制构造函数而不是移动构造函数?
- 基类中的默认析构函数禁用子类中的移动构造函数(如果有成员)
- 从具有按值捕获的 lambda 移动构造 std::函数时,移动构造函数调用两次
- 移动构造函数和右值引用
- 为什么 std::memmove 中联合的默认非平凡移动构造函数C++?
- 具有专用化的模板类中的可靠条件复制和移动构造函数
- C++:为什么不调用移动构造函数?
- 移动构造函数永远不会被调用
- C++:关于使用 Stroustrup 示例移动构造函数/赋值的问题
- 运算符+ 的规范实现涉及额外的移动构造函数
- C ++为什么在移动构造函数中需要移动/前进
- 为什么在删除"移动构造函数"时使用"复制构造函数"?
- 为什么这里不调用移动构造函数?
- 隐式移动构造函数
- 如何为具有私有成员的派生类实现移动构造函数
- 为什么不调用移动构造函数
- 是否可以避免在以下代码中复制/移动构造函数的需要?