我收到了以下代码:(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;
}
我有一个Factory
在Workers
处存储了一个向量。当我运行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 ++编写了一个月的代码并且在这里真的很挣扎。我已经谷歌搜索了一段时间,但无法找到提示,所以任何帮助都很棒!
答案 0 :(得分:7)
移动只移动对象的内容(如果这样实现,它可以只复制)。它并不意味着原始对象消失,只是它的值可能会改变。
您的示例在两个位置创建两个对象:
Worker w1 ("Bob");
this->workers.push_back (std::move (worker));
第二次偷走了第一次的内心(无论如何),但第一次仍然活着。任何生物对象都会在其生命周期结束时调用它的析构函数(对于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 ...