使用std::string属性的默认移动构造函数行为

3

我有一个简单的数据类,想要节省一些打字量,并让编译器生成移动构造函数和赋值操作符:

class A
{
public:
  A(int x, std::string&& y) : x_(x), y_(std::move(y)) {}
  A(A && a) = default;
  A& operator= (A && a) = default;
private:
  int x_;
  std::string y_;
};

假设我的编译器完全符合C++11标准,那么它会正确处理std::string y_属性吗?它会应用移动语义吗?


1
如果你的编译器符合C++标准,那么它将执行标准所要求的操作。因此,通常你不必担心编译器的行为;只需遵循语言规则即可。 - Kerrek SB
请注意,您的类现在具有已删除的复制构造函数(演示)。最好不要显式声明任何已经提供所需内容的隐式定义。 - Kerrek SB
1
你为什么认为不会呢?std::string是可移动的。 - NathanOliver
@NathanOliver:因为公平起见,C++的整个特性并不是非常表达。到处都有令人惊讶的考虑因素。std::move实际上并没有移动任何东西,这只是其中之一。我认为询问和检查是公平的! - Lightness Races in Orbit
@KerrekSB,事实上我的意图是删除复制构造函数。 - rustyx
2个回答

3
规则来自于[class.copy]:
非联合类X的隐式复制/移动构造函数执行其基类和成员的逐个复制/移动。因此,在这种情况下,它将从您正在移动构造/分配的A中移动构造/分配x_和y_。
请注意,默认的移动构造函数仍然可以执行复制操作,如果其成员之一具有未隐式定义的移动构造函数:
struct A {
    A() { }
    A(A const& ) { }
    // A(A&& ) not implicitly defined because of the copy ctor
};

struct B {
    B() = default;
    B(B&& ) = default;
    B& operator=(B&& ) = default;

    A a;
};

B b;
B c = std::move(b); // copy-constructs c.a from b.a

1
是的,这就是生成特殊成员函数的全部意义所在。
但是,您忘记将构造函数的参数移动到成员中了。
A(int x, std::string&& y) : x_(x), y_(std::move(y)) {}
//                                    ^^^^^^^^^^ ^

谢谢。在编写简化的测试用例时忘记了这一点。问题已更新。 - rustyx

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接