c++ 移动unique_ptr:重置源与销毁旧对象

jyztefdp  于 2023-04-13  发布在  其他
关注(0)|答案(1)|浏览(190)

我的问题是关于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)时,会发生三件事:
1.将head->next重置为nullptr;
1.将head设置为新值;
1.销毁head所指向的Node对象;
上面的代码工作意味着3保证发生在1之后,否则链接仍然存在。
我想知道是否有一个写下来的规则来保证这样的秩序,或者它只是一个隐藏的实现细节和例子只是工作。

uubf1zoe

uubf1zoe1#

head = std::move(head->next)时,会发生三件事:
1.将head->next重置为nullptr;
1.将head设置为新值;
1.销毁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按以下顺序执行其工作:
1.将head->next.release()的结果分配给存储的指针
1.删除指针以前存储的值
这种操作顺序也是标准的一部分,[unique.ptr.single.modifiers]/3:

constexpr void reset(pointer p = pointer()) noexcept;

效果:将p分配给存储指针,然后使用存储指针的旧值old_p计算if (old_p) get_deleter()(old_p);
长话短说-您的理解是正确的,并得到标准的保证

相关问题