简体   繁体   English

unique_ptr如何在超出范围时不破坏/释放它指向的内存?

[英]How does unique_ptr not destruct/release the memory it points to when it goes out of scope?

If I have a unnamed unique_ptr object, holding a object Foo, why will the object not be deleted when it is added to a vector? 如果我有一个未命名的unique_ptr对象,持有一个对象Foo,为什么该对象在被添加到向量时不会被删除?

Example: 例:

vec.push_back(std::unique_ptr<Foo>(new Foo())));

Why would Foo not be deleted? 为什么不删除Foo? I've attempted to implement this but I can't seem to figure this out, as I delete the object in the destructor. 我试图实现这个,但我似乎无法解决这个问题,因为我删除了析构函数中的对象。

The argument to std::vector::push_back is a temporary, so it will get passed to push_back as an rvalue reference . std::vector::push_back的参数是临时的,因此它将作为右值引用传递给push_back As you can see in the documentation , push_back has two forms, and the second takes an rvalue reference. 正如您在文档中看到的那样, push_back有两种形式,第二种形式采用右值引用。 The unique_ptr will get moved into the vector, and the temporary that you created for the argument will no longer own the memory. unique_ptr将被移动到向量中,并且为参数创建的临时将不再拥有内存。

You can't copy an std::unique_ptr ; 你不能复制std::unique_ptr ; if you tried to, you would get a compile error. 如果你试过,你会得到一个编译错误。 However, moving a unique pointer is perfectly allowable; 但是,移动一个独特的指针是完全允许的; the previous owner no longer owns the memory that it once pointed to. 前一个所有者不再拥有它曾经指向的内存。

In this case, since you're passing a temporary object, the move overload is called: void std::vector<T>::push_back(T&&) . 在这种情况下,由于您传递的是临时对象,因此调用移动重载: void std::vector<T>::push_back(T&&) Move semantics allow for nice optimization in situations where expensive copies aren't necessary. 移动语义允许在不需要昂贵副本的情况下进行很好的优化。 Without them, push_back would need to make a copy of the unique_ptr (which actually is not possible with the semantics of unique_ptr ) and you would indeed see the destructor being called. 如果没有他们, push_back需要做副本unique_ptr (这实际上是不可能的语义unique_ptr ),你确实会看到析构函数被调用。 With move semantics, the new unique_ptr inside the vector is essentially allowed to steal the contents of the temporary, and no copying takes place. 使用移动语义,向量内的新unique_ptr基本上允许窃取临时内容,并且不会发生复制。 See here for more explanation of move semantics. 有关移动语义的更多说明,请参见此处

This happens because unique_ptr doesn't have a copy constructor and instead must be moved everywhere. 发生这种情况是因为unique_ptr没有复制构造函数,而是必须移动到任何地方。

Here's what happens, in C++11 or 14, ignoring copy/move elision (because the rules changed, we're not allowed to ignore that in C++17): 以下是在C ++ 11或14中忽略复制/移动省略的情况(因为规则发生了变化,我们不允许在C ++ 17中忽略它):

  1. You construct a temporary unique_ptr<Foo> . 您构造一个临时的unique_ptr<Foo> This has the value category of prvalue , a type of rvalue. 它具有prvalue的值类别,即一种rvalue。
  2. The push_back method is called. 调用push_back方法 Because the parameter is the temporary created in 1., the second (rvalue reference) overload is called. 因为参数是在1中创建的临时参数,所以调用第二个(右值引用)重载。 This means that the value is moved in to vector. 这意味着该值将移入 vector。
  3. The vector uses unique_ptr 's move constructor (the fifth overload on that page), which creates a unique_ptr<Foo> managing the same Foo that the temporary in 1 does, and makes the temporary hold nullptr instead. 该向量使用unique_ptr的移动构造函数 (该页面上的第五个重载),它创建一个unique_ptr<Foo>管理与1中的临时值相同的Foo ,并使临时保持nullptr
  4. The statement completes and the temporary from 1. needs to be destroyed. 声明完成,需要销毁1的临时声明。 Its destructor is called. 它的析构函数被称为。 Because it holds nullptr , this does nothing in particular. 因为它持有nullptr ,所以没有特别的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM