代码之家  ›  专栏  ›  技术社区  ›  Krystian S

unique-ptr如何在超出范围时不销毁/释放它指向的内存?

c++
  •  2
  • Krystian S  · 技术社区  · 7 年前

    如果我有一个未命名的唯一的对象,持有一个对象foo,为什么当对象被添加到一个向量时它不会被删除?

    例子:

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

    为什么不删除foo?我试图实现这个,但是我似乎无法解决这个问题,因为我删除了析构函数中的对象。

    3 回复  |  直到 7 年前
        1
  •  6
  •   Silvio Mayolo    7 年前

    关于 std::vector::push_back 是暂时的,所以它会被传递给 push_back 作为 右值引用 是的。你可以从中看到 documentation , 向后推 有两种形式,第二种形式采用rvalue引用。这个 unique_ptr 会得到 移动 在向量中,为参数创建的临时项将不再拥有内存。

    你不能复制 std::unique_ptr ;如果尝试,则会出现编译错误。但是,移动唯一指针是完全允许的;以前的所有者不再拥有它曾经指向的内存。

        2
  •  3
  •   alter_igel    7 年前

    在这种情况下,由于传递的是临时对象,因此将调用移动重载: void std::vector<T>::push_back(T&&) 是的。移动语义允许在不需要昂贵拷贝的情况下进行良好的优化。没有他们, push_back 需要复印一份 unique_ptr (这实际上是不可能的,因为 独特的 )你会看到析构函数被调用。有了移动语义,新的 独特的 在向量内部基本上允许窃取临时文件的内容,并且不进行复制。见 here 更多关于移动语义的解释。

        3
  •  2
  •   Daniel H    7 年前

    这是因为 unique_ptr 没有复制构造函数,必须到处移动。

    这里发生了什么,在C++ 11或14中,忽略复制/移动省略(因为规则改变了,我们不允许在C++ 17中忽略它):

    1. 你建造了一个临时的 unique_ptr<Foo> 是的。它的值类别为 prvalue ,一种右值。
    2. 这个 push_back method 被称为。因为参数是1中创建的临时参数,所以调用第二个(rvalue引用)重载。这意味着这个值是 移动 在矢量中。
    3. 向量使用 unique_ptr 's move constructor (该页上的第五个重载),它创建 独特的&u ptr<foo> 同样的管理 Foo 临时的在1中执行,并使临时的 nullptr 相反。
    4. 语句完成,临时从1开始。需要销毁。 Its destructor 被称为。因为它能保存 零位 ,这没有什么特别的作用。