C ++对象不能被std :: move?

时间:2017-10-23 10:21:19

标签: c++ c++14 move

我收到了以下代码:(Code Live: C++ Shell

class Worker
{
public:
  Worker (std::string name):_name (name) {};

  Worker (const Worker & worker):_name (worker._name)
  {  std::cout << _name << " got copied!" << std::endl; }

  Worker (Worker && other):_name (other._name)
  {  std::cout << _name << " got moved!" << std::endl;  }

  ~Worker ()
  {  std::cout << _name << " got destroyed!" << std::endl;  }

  void changeName(std::string name)
  {  this->_name = name;  }

private:
  std::string _name;
};

class Factory
{
public:
  Factory ()
  {  std::cout << "Factory got created!" << std::endl;  }

   ~Factory ()
  {  std::cout << "Factory got destroyed!" << std::endl;  }

  void addWorker (Worker & worker)
  {  this->workers.push_back (std::move (worker));  }

  Worker & getLastWorker ()
  {  this->workers.back ();  }

private:
  std::vector < Worker > workers;
};
int main ()
{
  auto factory = std::make_unique < Factory > ();
  Worker w1 ("Bob");
  factory->addWorker (w1);
  Worker & workerRef = factory->getLastWorker ();
  //workerRef.changeName("Mary");

  return 0;
}

我有一个FactoryWorkers处存储了一个向量。当我运行main()时,我得到以下输出:

Factory got created!
Bob got moved!
Bob got destroyed!
Factory got destroyed!
Bob got destroyed!

但我无法理解Bob got destroyed!出现两次的原因,因为我认为Worker w1已移至workers中的向量Factory。此外,如果您在workerRef.changeName("Mary");中发表评论,则代码会因Segmentation fault而崩溃。

我现在用c ++编写了一个月的代码并且在这里真的很挣扎。我已经谷歌搜索了一段时间,但无法找到提示,所以任何帮助都很棒!

4 个答案:

答案 0 :(得分:7)

移动只移动对象的内容(如果这样实现,它可以只复制)。它并不意味着原始对象消失,只是它的值可能会改变。

您的示例在两个位置创建两个对象:

  1. Worker w1 ("Bob");
  2. this->workers.push_back (std::move (worker));
  3. 第二次偷走了第一次的内心(无论如何),但第一次仍然活着。任何生物对象都会在其生命周期结束时调用它的析构函数(对于w1它关闭main)。

答案 1 :(得分:5)

你还有两个对象,一个在main,一个在向量内。

&#34;移动&#34;实际上并没有移动一个对象,只有它的内容 - 至少在概念上(std::move只是一个类型转换)。
不一定是任何事情都会发生变化的情况,比如在你的情况下,&#34;移动构造函数&#34;行为与复制构造函数完全相同。

如果你想要更多的&#34; move-y&#34;移动构造函数,你应该写:_name (std::move(other._name)),这会使w1的名称为空。

崩溃的原因是您忘记在return中写getLastWorker 提高编译器的警告级别并注意它。

答案 2 :(得分:1)

首先,你的move-constructor并没有真正移动任何东西,它只是复制字符串。

当你将Worker推回向量时,你仍然有两个Worker个对象:一个在main函数中,一个在向量内。这两个对象都需要被破坏。

答案 3 :(得分:0)

很简单:

还会调用空对象析构函数。

move constractor中,旧对象将其内容(尤其是指针)传递给新对象,并变为空,然后在作为空对象的范围末尾将其销毁。

请注意,在移动构造函数之后,原始文件不应再调用Bob ...