【问题标题】:c++ copy constructor vs move constructor for std::vectorc ++复制构造函数与std :: vector的移动构造函数
【发布时间】:2018-03-12 19:34:54
【问题描述】:

我有一个类,其中包含 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 是使用复制构造函数构造的,M2 是使用“move”构造函数构造的,但是在 gdb 中运行时,两个分配都为 v 和 w 保留不同的地址,如果我使用 v (std::move( w)) 在第二个构造函数的初始化列表中。所以我猜这两个赋值都在复制 w 的内容,这是正确的吗?如果是这种情况,我该如何移动 w 的内容而不是复制它们

【问题讨论】:

  • “移动”部分指的是资源,而不是对象本身。
  • 看看地址v.data()

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


【解决方案1】:

首先,移动一个对象并不会改变它的地址。根据定义,您不能更改对象的地址,因为地址是对象定义的一部分。如果你有不同的地址,你就有不同的对象。移动的作用(至少对于标准库中的类而言)是转移对象动态分配资源的所有权。

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

所以移动向量的构造函数* 应该如下所示:

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

为了比较地址,看看它是否真的被移动了,你不应该比较vw的地址(那些不会,也不能改变),而是v.data()w.data() ,它指向vector动态分配的资源。

*不是移动构造函数。移动构造函数将具有签名 Mystruct(Mystruct&amp;&amp;)Mystruct(const Mystruct&amp;&amp;)

【讨论】:

    猜你喜欢
    • 2012-11-03
    • 1970-01-01
    • 2020-08-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-07
    相关资源
    最近更新 更多