我的问题是关于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)
时,有三件事发生:
- reset
head->next
tonullptr
; - 设置
head
为新值; - 销毁
head
用来指向的Node对象;
上面的代码工作意味着3保证发生在1之后,否则链接仍然存在
我想知道是否有一个书面的规则来保证这样的顺序,或者它只是一个隐藏的实现细节,例子只是工作。
当
head = std::move(head->next)
时,有三件事发生:
- reset
设置head->next
tonullptr
;head
为新值;销毁head曾经指向的Node对象;
在这种情况下,赋值操作符应该像调用head.reset(head->next.release())
函数一样工作,如[unique.ptr.single.asgn]/3:
constexpr unique_ptr& operator=(unique_ptr&& u) noexcept;
Effects:调用
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);
求值
长话短说-你的理解是正确的,并有标准的保证