我的问题是关于https://en.cppreference.com/w/cpp/memory/unique_ptr
中的例子struct List
{
struct Node
{
int data;
std::unique_ptr<Node> next;
};
std::unique_ptr<Node> head;
~List()
{
// destroy list nodes sequentially in a loop, the default destructor
// would have invoked its `next`'s destructor recursively, which would
// cause stack overflow for sufficiently large lists.
while (head)
head = std::move(head->next);
}
...
};
当
head = std::move(head->next)
时,会发生三件事:
head->next
为nullptr
;head
为新值;head
曾经指向的Node对象;上面的代码有效意味着 3 保证在 1 之后发生,否则链接仍然存在。
我想知道是否有一个写下来的规则来保证这样的顺序,或者它只是一个隐藏的实现细节,这个例子就可以了。
当
时,会发生三件事:head = std::move(head->next)
- 重置
为head->next
;nullptr
- 设置
为新值;head
- 销毁 head 指向的 Node 对象;
在这种情况下,赋值运算符应该像调用
head.reset(head->next.release())
函数一样工作,根据 [unique.ptr.single.asgn]/3:
无论如何,在这种情况下,constexpr unique_ptr& operator=(unique_ptr&& u) noexcept;
效果:调用
然后是reset(u.release())
.get_deleter() = std::forward<D>(u.get_deleter())
head->next.release()
必须先进行评估。 reset
按以下顺序执行其工作:
head->next.release()
的结果分配给存储的指针这个操作顺序也是标准的一部分,[unique.ptr.single.modifiers]/3:
constexpr void reset(pointer p = pointer()) noexcept;
效果:将p赋值给存储指针,然后用存储指针的旧值
,求值old_p
if (old_p) get_deleter()(old_p);
长话短说——你的理解是正确的,并由标准保证