问题描述
// code from https://skillsmatter.com/skillscasts/2188-move-semanticsperfect-forwarding-and-rvalue-references
class Widget {
public:
Widget(Widget&& rhs)
:pds(rhs.pds)//获取源值
{
rhs.pds = nullptr; //为什么?
}
private:
struct DataStructure;
DataStructure * pds;
}
我不明白设置 rhd.pds $
到
nullptr
。
如果我们删除此行,会发生什么:
rhs.pds = nullptr; 解决方案类的一些细节已被删除。特别是,构造函数动态分配 DataStructure
对象,析构函数释放它。如果在移动过程中,你只是将指针从 Widget
复制到另一个, Widget
同样分配 DataStructure
对象。然后,当这些对象被销毁时,它们都会尝试 delete
。这将给出未定义的行为。为了避免这种情况,正在移动的 Widget
将其内部指针设置为 nullptr
。
这是实现移动构造函数时的标准模式。您希望将某些动态分配的对象的所有权从一个对象移动到另一个对象,因此您需要确保原始对象不再拥有这些已分配对象。
从这个情况开始,希望将 DataStructure
的所有权从一个 Widget
移动到另一个:
┌───────┐
│小部件││小部件│
└───╂────┘└───────┘
┃
▼
┌───────── ────┐
│数据结构│
└──────┘
如果你刚刚复制指针,你会有:
──────────
│小部件││小部件│
└───╂────┘└───╂─── ─┘
┗━━━━━━━━━━━━┛
▼
┌────────────┐┐
│数据结构│
└────────────┘
如果然后将原始 Widget
指针设置为 nullptr
,则您具有:
┌───────┐
│小部件││小部件│
└──────┘└───╂────┘
┃
▼
┌──────── ─────┐
│数据结构│
└──────┘
所有权已成功转移,且 Widget
可以销毁而不会导致未定义的行为。
//code from https://skillsmatter.com/skillscasts/2188-move-semanticsperfect-forwarding-and-rvalue-references
class Widget {
public:
Widget(Widget&& rhs)
: pds(rhs.pds) // take source’s value
{
rhs.pds = nullptr; // why??
}
private:
struct DataStructure;
DataStructure *pds;
};
I can't understand the reason for setting rhd.pds
to nullptr
.
What will happen if we remove this line : rhs.pds = nullptr;
解决方案 Some details of the class have been removed. In particular, the constructor dynamically allocates the DataStructure
object and the destructor deallocates it. If, during a move, you just copied the pointer from one Widget
to another, both Widget
s would have pointers to the same allocated DataStructure
object. Then, when those objects are destroyed, they would both attempt to delete
it. This would give undefined behaviour. To avoid this, the Widget
that is being moved from has its internal pointer to set to nullptr
.
This a standard pattern when implementing a move constructor. You want to move ownership of some dynamically allocated objects from one object to another, so you need to make sure the original object no longer owns those allocated objects.
Diagrammatically, you start off with this situation, wanting to move ownership of the DataStructure
from one Widget
to the other:
┌────────┐ ┌────────┐
│ Widget │ │ Widget │
└───╂────┘ └────────┘
┃
▼
┌───────────────┐
│ DataStructure │
└───────────────┘
If you just copied the pointer, you'd have:
┌────────┐ ┌────────┐
│ Widget │ │ Widget │
└───╂────┘ └───╂────┘
┗━━━━━━━━┳━━━━━━━┛
▼
┌───────────────┐
│ DataStructure │
└───────────────┘
If you then set the original Widget
pointer to nullptr
, you have:
┌────────┐ ┌────────┐
│ Widget │ │ Widget │
└────────┘ └───╂────┘
┃
▼
┌───────────────┐
│ DataStructure │
└───────────────┘
Ownership has successfully been transferred, and when both Widget
s can be destroyed without causing undefined behaviour.
这篇关于为什么我们需要在移动构造函数中将右值引用设置为null?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!