unique_ptr 何时被释放?

When a unique_ptr is deallocated?

在此代码中:

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 移到那里的,但我不确定也不相信这个答案。

您正在转让 所有权从 pq,因此 q 现在拥有该资源。因此,一旦 q 被销毁,即在函数 f.

结束时,您的整数就会被销毁

唯一指针本身在其作用域结束时被销毁,即 pg() 时被销毁 returns 并且 q 在 [=18= 时被销毁] returns.

另见 this small example

At which line p is deallocated?

p是对象,对象可以销毁。可以 释放 .

的内存

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

p 本身在控制离开 g 时被销毁(此时 p 为空,即不指向任何东西)。

At which line p is deallocated?

在声明它的作用域的末尾,即本例中的函数 g。即销毁具有自动存储的对象,并释放其内存。

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

为了清楚起见,请按以下方式更改您的代码片段

#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 退出的那一刻,析构函数被调用。

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...