c ++拷贝构造函数vs std :: vector

时间:2017-10-01 14:44:48

标签: c++ copy-constructor move-constructor

我有一个类似<{1}}的类

std::vector

我创建像

这样的对象
struct Mystruct
{
  Mystruct(const std::vector<int>& w): v(w) 
  {
    std::cout << "Copy constructor :" << v.at(0) << "\n";
  }
  Mystruct(const std::vector<int>&& w): v(w)
  {
    std::cout << "Move Constructor :" << v.at(0) << "\n";
  }
  private:
  std::vector<int> v;
};

int main() { auto x = std::vector<int> {1,2,3}; Mystruct M1(x); Mystruct M2(std::vector<int> {3,2,1}); return 0; } 使用复制构造函数构建,M1使用&#34;移动&#34;构造函数,但是在gdb中运行时,两个assignements都为v和w保留不同的地址,如果我在第二个构造函数的初始化列表中使用v(std :: move(w)),则会发生同样的情况。所以我猜两个人都在复制w的内容,这是正确的吗?如果是这种情况,我怎样才能移动w的内容而不是复制它们

1 个答案:

答案 0 :(得分:12)

首先,移动对象不会改变其地址。根据定义,您不能更改对象的地址,因为地址是对象定义的一部分。如果您有不同的地址,则会有不同的对象。什么移动(至少在标准库中的类)是移动对象的动态分配资源的所有权。

其次,你没有动任何东西。为了移动东西,你必须调用移动构造函数。这意味着你需要传递一个r值。命名对象永远不是r值。因此,即使您有r值引用,仍需要使用std::move进行转换。但在你的情况下,即使这还不够。在标准库中,所有移动构造函数都具有Type(Type&&)的签名,而不是Type(const Type&&)。如果传递一个const值,即使用std::move强制转换它,它也会调用复制构造函数,而不是移动构造函数。为了调用移动构造函数,您的对象不能是const。

因此,移动向量 * 的构造函数应如下所示:

Mystruct(std::vector<int>&& w): v(std::move(w))
{
    std::cout << "Move Constructor :" << v.at(0) << "\n";
}

为了比较地址以查看它是否实际被移动,您不应该比较vw的地址(那些不会,也不能更改),但是{{1 }和v.data(),它指向向量的动态分配资源。

*不是移动构造函数。移动构造函数将具有签名w.data()Mystruct(Mystruct&&)