Bootstrap

C++智能指针

unique_ptr

std::unique_ptr 是 C++ 中的一种智能指针,它表示对其所指向对象的独占所有权。,它表示对象的唯一所有权。std::unique_ptr 实例在离开作用域时会自动删除其所指向的对象,以下是 std::unique_ptr 的一些常见用法:

  1. 创建 std::unique_ptr:你可以使用 new 关键字创建一个 std::unique_ptr
std::unique_ptr<int> p1(new int(5));

但是,更推荐的方式是使用 std::make_unique 函数,这样可以避免原始指针暴露,并提供更好的异常安全性:

std::unique_ptr<int> p1 = std::make_unique<int>(5);
  1. 访问 std::unique_ptr 所指向的对象:你可以使用 *-> 运算符来访问 std::unique_ptr 所指向的对象:
*p1 = 10;  // 使用 * 运算符
p1->method();  // 使用 -> 运算符,假设 p1 指向的对象有一个名为 method 的成员函数
  1. 移动 std::unique_ptr:由于 std::unique_ptr 表示独占所有权,所以你不能复制 std::unique_ptr,但你可以移动它:
std::unique_ptr<int> p2 = std::move(p1);  // 现在 p2 拥有对象,p1 不再拥有对象
  1. 删除 std::unique_ptr 所指向的对象:当 std::unique_ptr 被销毁(例如,当它离开其作用域)时,它会自动删除其所指向的对象。你也可以手动删除对象,方法是调用 std::unique_ptr::reset 方法:
p2.reset();  // 删除 p2 所指向的对象,现在 p2 不再指向任何对象
  1. 检查 std::unique_ptr 是否为空:你可以像检查原始指针一样检查 std::unique_ptr 是否为空:
if (p2) {  // 如果 p2 不为空
    // ...
}

传递给函数

std::unique_ptr 的设计目标是拥有其所指向的对象的独占所有权,因此你不能通过复制将 std::unique_ptr 传递给函数。但是,你可以通过引用或移动语义将 std::unique_ptr 传递给函数。

  1. 通过引用传递:如果你的函数只需要访问 std::unique_ptr 所指向的对象,但不需要接管所有权,你可以将 std::unique_ptr 作为常量引用传递:
void f(const std::unique_ptr<int>& p) {
    // 访问 p 所指向的对象,但不接管所有权
    std::cout << *p << std::endl;
}
  1. 通过移动语义传递:如果你的函数需要接管 std::unique_ptr 所指向的对象的所有权,你可以通过 std::movestd::unique_ptr 传递给函数:
void g(std::unique_ptr<int> p) {
    // 接管 p 所指向的对象的所有权
    *p = 10;
}

std::unique_ptr<int> p = std::make_unique<int>(5);
g(std::move(p));  // 将 p 的所有权移动到 g

在这个例子中,g(std::move(p))p 的所有权移动到 g。在这个调用之后,p 不再拥有其原来所指向的对象。

weak_ptr

std::weak_ptr 是 C++ 中的一种智能指针,它是 std::shared_ptr 的弱引用。std::weak_ptr 不会增加其所指向对象的引用计数,因此它不会阻止对象被删除。它通常用于解决 std::shared_ptr 的循环引用问题。

以下是 std::weak_ptr 的一些常见用法:

  1. 创建 std::weak_ptr:你可以从 std::shared_ptr 创建一个 std::weak_ptr
std::shared_ptr<int> p1 = std::make_shared<int>(5);
std::weak_ptr<int> w1 = p1;  // 创建一个弱引用
  1. 访问 std::weak_ptr 所指向的对象:由于 std::weak_ptr 不拥有其所指向的对象,所以你不能直接通过 std::weak_ptr 访问对象。你需要先将 std::weak_ptr 提升为 std::shared_ptr
if (std::shared_ptr<int> p2 = w1.lock()) {  // 提升为 std::shared_ptr
    std::cout << *p2 << std::endl;  // 访问对象
} else {
    std::cout << "Object has been deleted." << std::endl;
}
  1. 检查 std::weak_ptr 是否为空:你可以使用 std::weak_ptr::expired 方法检查 std::weak_ptr 是否为空:
if (w1.expired()) {  // 如果 w1 为空
    // ...
}
  1. 获取 std::weak_ptr 所指向的对象的引用计数:你可以使用 std::weak_ptr::use_count 方法获取 std::weak_ptr 所指向的对象的引用计数:
std::cout << w1.use_count() << std::endl;  // 打印引用计数

请注意,std::weak_ptr 主要用于解决 std::shared_ptr 的循环引用问题。例如,如果你有两个类 A 和 B,它们互相持有对方的 std::shared_ptr,那么这两个对象将永远不会被删除,因为它们的引用计数永远不会变为 0。在这种情况下,你可以使用 std::weak_ptr 来打破这个循环。

std::shared_ptrstd::weak_ptrstd::unique_ptr 都是 C++ 中的智能指针,它们用于自动管理动态分配的内存,以防止内存泄漏。它们的主要区别在于所有权和生命周期管理:

  • std::unique_ptr 表示对其所指向对象的独占所有权。也就是说,同一时间只能有一个 std::unique_ptr 指向一个给定的对象。当 std::unique_ptr 被销毁时,它所指向的对象也会被删除。std::unique_ptr 不能被复制,但可以被移动,这意味着你可以将所有权从一个 std::unique_ptr 转移到另一个 std::unique_ptr

  • std::shared_ptr 允许多个 std::shared_ptr 对象共享对同一个对象的所有权。std::shared_ptr 使用引用计数来跟踪有多少个 std::shared_ptr 对象指向同一个对象。当最后一个 std::shared_ptr 被销毁时,它所指向的对象也会被删除。

  • std::weak_ptr 是一种特殊的 std::shared_ptr,它不会增加其所指向对象的引用计数。这意味着 std::weak_ptr 不会阻止其所指向的对象被删除。std::weak_ptr 主要用于解决 std::shared_ptr 的循环引用问题。你可以通过 std::weak_ptr::lock 方法将 std::weak_ptr 提升为 std::shared_ptr,如果对象还存在,lock 方法会返回一个新的 std::shared_ptr,指向该对象,并增加其引用计数。如果对象已经被删除,lock 方法会返回一个空的 std::shared_ptr

总的来说,std::unique_ptrstd::shared_ptrstd::weak_ptr 提供了不同级别的所有权和生命周期管理,你可以根据你的具体需求选择使用哪一种。

;