unique_ptr :: release()是否调用析构函数?


78

此代码正确吗?

auto v =  make_unique<int>(12);
v.release();     // is this possible?

它等于delete原始指针吗?

Answers:


163

不,代码会导致内存泄漏。release用于释放托管对象的所有权而不删除它:

auto v = make_unique<int>(12);  // manages the object
int * raw = v.release();        // pointer to no-longer-managed object
delete raw;                     // needs manual deletion

除非您有充分的理由在没有安全网的情况下处理原始内存,否则请不要这样做。

要删除对象,请使用reset

auto v = make_unique<int>(12);  // manages the object
v.reset();                      // delete the object, leaving v empty

9
作为一个完全题外话切,我见过的人写的int* rawint *raw,但是这是我第一次见过int * raw
科里克莱默

13
@Cyber​​:这是一个品味问题。我不认为指针限定符是“附加”到类型或变量上的,因此我不将其附加到任何一个上。
Mike Seymour 2014年

13
如果很难过,他们决定使用这些函数名称。像detach这样的东西会比release
minexew

1
@eepp会破坏对象还是只是喜欢release
tuket

1
我不同意@nenchev。我认为来自nullptr的分配更加明确。除了删除指向的对象(它是unique_ptr)外,它几乎无能为力,因为它显然是用nullptr替换当前值。对于reset(),您必须阅读文档以确保该功能的确切作用。
MadScientist

28

此代码正确吗?

否。std::unique_ptr<>::reset()用于删除内部原始指针:

auto v =  std::make_unique<int>(12);
v.reset(); // deletes the raw pointer

完成之后,std::unique_ptr<>::get()将返回nullptr(除非您向提供了非nullptr参数std::unique_ptr<>::reset())。


21

此代码正确吗?

它不是,并且会泄漏。

release()只需让调用代码收回对unique_ptr被调用之前所持有内存的所有权即可。如果不分配所返回的指针release(),则只会发生泄漏。

的显式删除unique_ptr将为reset()。但是请记住,unique_ptr它们在那里,以便您不必直接管理它们所拥有的内存。也就是说,您应该知道,unique_ptr一旦a超出范围,它将安全地删除其基础原始指针。

因此,您应该有充分的理由对自动内存管理对象执行手动内存管理。


12

release 由于您未将原始指针分配给任何对象,因此它将泄漏您的原始指针。

它旨在用于类似

int* x = v.release();

这意味着v不再管理该指针的生存期,而是将原始指针所有权委托给x。如果只是release不分配任何内容,则会泄漏原始指针。


啊,我明白了。因此,在我的代码中,我一直在使用,.get()然后.reset()在周围交换内容,但实际上我要执行的操作是在.release()后面.reset(),以确保.reset()调用不会delete出现旧对象。.release()然后.get()释放指针后,执行与相同的功能。
安德鲁

或可能.reset()只是简单的post-后.release()
安德鲁

A.get()后跟a.reset()会引起问题。该.get()会给你一个不拥有指针,然后.reset()将调用delete,因此你的原始指针从get现已形成“悬摆指针”,并访问它是未定义的行为。
科里·克莱默

2

对于任意类型,可能有点棘手:

  unique_ptr<Foo> v = get_me_some_foo();  // manages the object
  Foo * raw = v.release();        // pointer to no-longer-managed object
  delete raw;

几乎是正确的。

  unique_ptr<Foo> v = get_me_some_foo();  // manages the object
  Foo * ptr = v.release();        // pointer to no-longer-managed object
  v.get_deleter() ( ptr );

这在所有情况下都是正确的;可能在Foo类型上定义了一个自定义删除器,但是在所有情况下都使用unique_ptr对象返回的删除器是好的。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.