考虑到以下类,实现 move 构造函数的正确方法是什么:
class C {
public:
C();
C(C&& c);
private:
std::string string;
}
当然,这样做的目的是避免复制 string
或将其释放两次。
让我们假设基本示例只是为了清楚起见,我确实需要一个 move 构造函数。
我试过了:
C::C(C&& c) {
//move ctor
string = std::move(c.string);
}
和
C::C(C&& c) : string(std::move(c.string)) {
//move ctor
}
两者都可以在 gcc 4.8 上编译并运行良好。 似乎选项 A 是正确的行为,string
被复制而不是与选项 B 一起 move 。
这是 move 构造函数的正确实现吗?
最佳答案
由于 std::string
本身有一个 move-ctor,因此为 C
隐式定义的 move-ctor 将负责正确的 move 操作。您可能无法自己定义。但是,如果您有任何其他数据成员,特别是:
12.8 Copying and moving class objects
12 An implicitly-declared copy/move constructor is an inline public member of its class. A defaulted copy- /move constructor for a class X is defined as deleted (8.4.3) if X has:
— a variant member with a non-trivial corresponding constructor and X is a union-like class,
— a non-static data member of class type M (or array thereof) that cannot be copied/moved because overload resolution (13.3), as applied to M’s corresponding constructor, results in an ambiguity or a function that is deleted or inaccessible from the defaulted constructor, or
— a direct or virtual base class B that cannot be copied/moved because overload resolution (13.3), as applied to B’s corresponding constructor, results in an ambiguity or a function that is deleted or inaccessible from the defaulted constructor, or
— for the move constructor, a non-static data member or direct or virtual base class with a type that does not have a move constructor and is not trivially copyable.
13 A copy/move constructor for class X is trivial if it is neither user-provided nor deleted and if
— class X has no virtual functions (10.3) and no virtual base classes (10.1), and functions (10.3) and no virtual base classes (10.1), and
— the constructor selected to copy/move each direct base class subobject is trivial, and
— for each non-static data member of X that is of class type (or array thereof), the constructor selected to copy/move that member is trivial; otherwise the copy/move constructor is non-trivial.
您可能想要实现自己的 move-ctor。
如果您需要 move-ctor,请首选初始化列表语法。总是!否则,您最终可能会得到初始化列表中未提及的每个对象的默认构造(对于具有非默认 ctors 的成员对象,您必须这样做)。
关于C++11 move 构造函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10402241/