由 const std::unique_ptr 管理的对象的生命周期

lifetime of an object managed by const std::unique_ptr

我在 std::unique_ptr reference 中看到以下注释:

Only non-const unique_ptr can transfer the ownership of the managed object to another unique_ptr. The lifetime of an object managed by const std::unique_ptr is limited to the scope in which the pointer was created.

有谁能举例说明一下吗?我想不通为什么。

您根本无法从 const std::unique_ptr 移动,也不能使用其他修改成员函数 - swapreleasereset(这些在逻辑上是非常量限定,不能在 const 实例上调用。

转让所有权意味着将旧所有者重置为非拥有状态,从而对其进行修改。


const std::unique_ptr 将在其生命周期内(从其初始化开始)最多管理 个对象。
如果 std::unique_ptr const&,您将无法通过此引用(const 正确性)从引用(甚至非 const)std::unique_ptr 转移所有权。

resetreleaseswap 和移动赋值函数是非常量成员函数,因此不能与 std::unique_ptr 的 const 实例一起使用class。因此,const std::unique_ptr 无法被修改,并被迫拥有指针,直到它超出范围。

通常您可以通过使用移动赋值或移动构造函数将托管对象的所有权转移给另一个unique_ptr,例如:

std::unique_ptr<int> p(new int(1));
std::unique_ptr<int> q(std::move(p)); 
//now q owns the pointer, which is freed when q is destructed

但如果 pconst,您将无法这样做,并且当 p 被销毁时,托管对象将被释放:

const std::unique_ptr<int> p(new int(1));
std::unique_ptr<int> q(std::move(p));  //compilation error

A unique_ptr 拥有它指向的内存。

void MyFunc()
{ 
    // Creates a unique pointer that points at a Foo object.
    std::unique_ptr<Foo> foo = std::make_unique<Foo>();

    // ... do some stuff, then return
}

在这个例子中,我们创建了一个 Foo 对象并将其分配给我们的 unique_ptr。通常当你创建堆上的东西时,你必须使用 new 在堆中为它分配 space 并构造它,并使用 delete 销毁它并释放它的 space.在这里,一旦您离开创建 unique_ptr 的范围(在本例中是函数的末尾),unique_ptr 就会处理释放。

Only non-const unique_ptr can transfer the ownership of the managed object to another unique_ptr.

这意味着您可以将指针的所有权转让给另一个 unique_ptr,但前提是它没有标记为常量。一次只有一个 unique_ptr 可以拥有一个对象。

一种方法是这样的:

std::unique_ptr<Foo> foo1 = std::make_unique<Foo>();
std::unique_ptr<Foo> foo2 = std::move(foo1);

现在 foo1 中的指针已移至 foo2foo1 不再管理该内存,foo2 是。

The lifetime of an object managed by const std::unique_ptr is limited to the scope in which the pointer was created.

这意味着当您的 unique_ptr 离开范围时,它会删除它指向的对象。就好像你这样做了:

void MyFunc()
{ 
    Foo* foo = new Foo()

    // ... do some stuff, then return

    delete foo;
}

好处是现在您不必手动调用 delete,这很好,因为如果您忘记删除它可能会造成内存泄漏。