Bootstrap

share_ptr引用计数

1 share_ptr引用

std::shared_ptr是 C++11 及以后版本中提供的智能指针类型之一,它允许多个std::shared_ptr对象共享所有权(ownership)的一个对象。当没有任何std::shared_ptr` 对象指向该对象时,该对象将被自动删除。

与裸指针(raw pointer)相比,std::shared_ptr 的优点在于它可以自动管理对象的生命周期,从而减少内存泄漏和其它资源管理上的问题。

以下是关于 std::shared_ptr 的一些基本概念:

  1. 引用计数std::shared_ptr 使用引用计数来跟踪有多少个 std::shared_ptr 实例指向同一个对象。当你创建一个新的 std::shared_ptr 以共享一个已有的对象时,引用计数会增加。当 std::shared_ptr 被销毁时,引用计数会减少。当引用计数变为 0 时,它指向的对象也会被销毁。

  2. make_shared:这是创建 std::shared_ptr 的推荐方法,它在一个内存分配中同时创建对象和控制块(包含引用计数等信息)。这可以比单独为对象和控制块分配内存更为高效。

std::shared_ptr<int> p = std::make_shared<int>(42);
  1. 赋值和拷贝:你可以安全地将一个 std::shared_ptr 赋给另一个。这样,两者都会指向同一个对象,且引用计数会适当增加。
std::shared_ptr<int> p1 = std::make_shared<int>(42);
std::shared_ptr<int> p2 = p1;  // Both p1 and p2 now point to 42, reference count is 2
  1. 用于数组:虽然 std::shared_ptr 可以用于数组,但推荐使用 std::vector 或其他容器来管理动态数组。

  2. 循环引用:这是 std::shared_ptr 的一个潜在陷阱。如果你有两个对象,它们互相持有对方的 std::shared_ptr,那么这两个对象永远不会被删除,因为它们的引用计数永远不会达到0。为了解决这个问题,C++ 提供了 std::weak_ptr,它是一个不增加引用计数的智能指针,常与 std::shared_ptr 一同使用来避免循环引用。

最后,建议深入学习相关的文档和例子,实践一些小程序以帮助你更好地理解和使用 std::shared_ptr

#################
当然可以。以下是一个简单的程序,演示了 std::shared_ptr 的引用计数的变化:

#include <iostream>
#include <memory>

int main() {
   
    // 创建 shared_ptr
    std::shared_ptr<int> sp1 = std::make_shared<int>(10);
    std::cout << "sp1 reference count: " << sp1.use_count() << std::endl;  // 输出:1

    // 创建一个 shared_ptr 并复制给 sp2
    std::shared_ptr<int> sp2 = sp1;
    std::cout << "sp1 reference count after assigning to sp2: " << sp1.use_count() << std::endl;  // 输出:2
    std::cout << "sp2 reference count: " << sp2.use_count() << std::endl;  // 输出:2

    // 创建一个新的 shared_ptr 并赋值给 sp3
    std::shared_ptr<int> sp3;
    sp3 = sp1;
    std::cout << "sp1 reference count after assigning to sp3: " << sp1.use_count() << std::endl;  // 输出:3

    // 重置 sp2,断开与原对象的关联
    sp2.reset();
    std::cout << "sp1 reference count after sp2 reset: " << sp1.use_count() << std::endl;  // 输出:2

    // sp3 离开其作用域
    {
   
        std::shared_ptr<int> sp3_local = sp1;
        std::cout << "sp1 reference count inside scope: " << sp1.use_count() << std::endl;  // 输出:3
    }

    std::cout << "sp1 reference count after scope: " << sp1.use_count() << std::endl;  // 输出:2

    return 0;
}

在这个程序中,我们多次输出了引用计数,以便观察不同操作(如赋值、重置、离开作用域等)对引用计数的影响。

2 share_ptr中的重置

当你对一个 std::shared_ptr 调用 reset() 方法后,这个 shared_ptr 将不再指向之前的对象(如果之前有的话)。更具体地说,sp2 将成为一个空的 shared_ptr,它不指向任何对象。

如果你尝试解引用一个已经被 reset()shared_ptr,程序将引发运行时错误。

在你给出的示例中,调用 sp2.reset() 后,sp2 将不再指向之前的整数对象。如果你检查 sp2 是否指向一个对象,结果将为 false

if (

悦读

道可道,非常道;名可名,非常名。 无名,天地之始,有名,万物之母。 故常无欲,以观其妙,常有欲,以观其徼。 此两者,同出而异名,同谓之玄,玄之又玄,众妙之门。

;