当一个unique_ptr被释放时会发生什么?

3
在这段代码中:
void f(std::unique_ptr<int> q)
{
}

void g()
{
    std::unique_ptr<int> p{new int{42}};
    f(std::move(p));
}

在哪一行释放p?我觉得是在f函数退出时,因为它被使用std::move移动到那里,但我对这个答案不确定也不自信。

5个回答

7

在哪一行p被释放?

p在它声明的作用域结束时被释放,即在本例中的函数g。这是当具有自动存储的对象被销毁并且它们的内存被释放时发生的。

您初始化为42的动态存储整数将被q的析构函数在f的结尾处释放。这是因为移动构造转移了所有权。


6

p在哪一行被释放?

p是一个对象,对象可以被销毁。它所占用的内存可以被释放

p最初指向的内存(由new int {42}分配)在控制权离开f时(即q被销毁时)被释放。

p本身在控制权离开g时被销毁(此时pnull,即不再指向任何内容)。


2
为了让内容更加清晰易懂,请按照以下方式更改您的代码片段。
#include <iostream>
#include <memory>
#include <utility>

struct A
{
    ~A() { std::cout << "~A()\n"; }
};

void f(std::unique_ptr<A> q)
{
    std::cout << "f() begins\n";
}

void g()
{
    std::cout << "g() begins\n";
    std::unique_ptr<A> p{new A };
    f( std::move( p ) );
    std::cout << "p == nullptr is " << ( p == nullptr ) << '\n';
    std::cout << "g() endss\n";
}

int main() 
{
    std::cout << "Within main()\n";
    g();

    return 0;
}

程序输出为:
Within main()
g() begins
f() begins
~A()
p == nullptr is 1
g() endss

因此,函数g将所指对象的所有权转移给了函数f。函数f结束时没有将所指对象的所有权转移给其他函数。因此,在函数f退出时调用了析构函数。

1
我不会说g在任何地方转移了对p的所有权。p仍然是由g作为自动变量“拥有”的。转移的是动态分配对象的所有权。 - Daniel Langr
1
@DanielLangr 当我们讨论所有权时,我们指的是分配对象的拥有权,而不是局部变量的拥有权。 - Vlad from Moscow

1
你正在将所有权从 p 转移给 q,因此 q 现在拥有该资源。因此,当函数 f 结束时,即在 q 被销毁时,你的整数也将被销毁。
唯一指针本身在其作用域结束时被销毁,即在 g() 返回时销毁 p,在 f() 返回时销毁 q
另请参见 这个小例子

1

p将在退出g函数时被销毁,就像具有局部作用域的任何其他变量一样。仅在那个时候,它不再保存数据;为了理解,您实际上不需要单独的函数,只需考虑以下内容:

int* n = new int(42);

{
    std::unique_ptr<int> p(n); // p how owns the value pointed to by n
                               // for brevity, I'll say p owns n from now on,
                               // although technically not correct...

    { // opening another scope! (corresponds to function call)
        std::unique_ptr<int> q; // another variable, nothing else is a
                                // function parameter either...

        q = std::move(p);       // this happens, too, when calling a function
                                // at this point, the ownership is transferred to q
                                // q now owns n, p is left with just nothing
                                // (i. e. now holds a null-pointer)
    } // at this point, q is going out of scope; as it is the current
      // owner of n, it will delete it

    // p still is in scope, but it has transferred ownership, remember?

} // at this point, p is destroyed; as it doesn't own anything at all any more
  // it dies without doing anything either...

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接