考虑以下代码:
#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
的对象。
我很确定我的推理中遗漏了一些东西,但我无法弄清楚哪里出了问题。
这是一个安全的操作吗?标准在哪里让我放心?
最佳答案
我认为这一切都非常安全。当您调用 f()
在 foo
上运行, class Foo
的移动赋值运算符将调用 std::unique_ptr<Foo>::operator=(std::unique_ptr<Foo>&&)
.现在,C++14 标准,§20.8.1.2.3,逗号 2,说:
Effects: Transfers ownership from
u
to*this
as if by callingreset(u.release())
followed byget_deleter() = std::forward<D>(u.get_deleter())
.
在 §20.8.1.2.5,逗号 4,我们发现 reset()
的行为:
Effects: assigns
p
to the stored pointer, and then if the old value of the stored pointer,old_p
, was not equal tonullptr
, callsget_deleter()(old_p)
. [ Note: The order of these operations is significant because the call toget_deleter()
may destroy*this
. —end note ]
因此,我们可以争辩说,存储的指针 将被替换,然后旧的存储指针 将按此顺序被删除。因此,一切都很好并且定义明确。
此外,当您输入 reset()
时功能,*foo.next
对象已经是release()
d,所以尖头物体不会被它破坏。
关于c++ - 关于涉及唯一指针的安全操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42133510/