关于涉及唯一指针的安全操作

时间:2017-02-09 09:59:57

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

请考虑以下代码:

false

通过#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的对象。
我很确定我在推理中遗漏了一些东西,但我无法弄清楚出了什么问题 这是安全的操作吗?标准在哪里让我放心?

1 个答案:

答案 0 :(得分:7)

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

  

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

在§20.8.1.2.5,逗号4中,我们找到了reset()的行为:

  

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

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

此外,当您输入进入reset()函数时,*foo.next对象已经是release() d,因此指向的对象不会被它摧毁。