【问题标题】:About safe operations involving unique pointers关于涉及唯一指针的安全操作
【发布时间】:2017-06-27 06:35:09
【问题描述】:

考虑以下代码:

#include <memory>

struct Foo { std::unique_ptr<Foo> next; };
void f(Foo &foo) { foo = std::move(*foo.next); }

int main() {
    Foo foo{};
    foo.next = std::make_unique<Foo>();
    foo.next->next = std::make_unique<Foo>();
    f(foo);
}

通过执行foo = std::move(*foo.next);foo.next.next 被移动到foo.next
如果foo.next 作为第一步无效,则可以立即删除它指向的对象。这将导致删除 foo.next.next,这是我试图移动到 foo.next 的对象。
我很确定我的推理中遗漏了一些东西,但我不知道出了什么问题。
操作安全吗?标准在哪里让我对此感到放心?

【问题讨论】:

    标签: c++ c++14 unique-ptr


    【解决方案1】:

    我认为这一切都非常安全。当您在foo 上调用f() 函数时,class Foo 的移动赋值运算符将调用std::unique_ptr&lt;Foo&gt;::operator=(std::unique_ptr&lt;Foo&gt;&amp;&amp;)。现在,C++14 标准 §20.8.1.2.3,逗号 2 说:

    效果:将所有权从u 转移到*this,就像调用reset(u.release()) 后跟get_deleter() = std::forward&lt;D&gt;(u.get_deleter())一样。

    在 §20.8.1.2.5,逗号 4 处,我们发现 reset() 的行为:

    效果:p 分配给存储指针,然后如果存储指针的旧值old_p 不等于nullptr,则调用get_deleter()(old_p)。 [ 注意:这些操作的顺序很重要,因为对get_deleter() 的调用可能会破坏*this——尾注 ]

    因此,我们可以争辩说,存储的指针将被替换,然后旧的存储指针将被删除,按照这个顺序。因此,一切都很好并且定义明确。

    此外,当你进入reset()函数时,*foo.next对象已经是release()d,所以指向的对象不会被它破坏。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-08-25
      • 1970-01-01
      • 2023-03-18
      • 2020-05-14
      • 2012-07-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多