与旨在独占资源的 std::unique_ptr 不同,std::shared_ptr 专门解决多个智能指针共同拥有同一资源的需求。
这意味着可以有任意数量的 std::shared_ptr 指向同一对象。内部通过引用计数(reference count)来跟踪共享该资源的 std::shared_ptr 数量。只要至少还有一个 std::shared_ptr 指向该资源,资源就不会被释放;当最后一个 std::shared_ptr 离开作用域或被重新赋值时,资源才被析构。
与 std::unique_ptr 一样,std::shared_ptr 位于头文件 <memory>。
示例:共享所有权
#include <iostream>
#include <memory> // for std::shared_ptr
class Resource
{
public:
    Resource()  { std::cout << "Resource acquired\n"; }
    ~Resource() { std::cout << "Resource destroyed\n"; }
};
int main()
{
    Resource* res{ new Resource };
    std::shared_ptr<Resource> ptr1{ res };
    {
        std::shared_ptr<Resource> ptr2{ ptr1 }; // 由 ptr1 拷贝构造
        std::cout << "Killing one shared pointer\n";
    } // ptr2 离开作用域,但资源仍在
    std::cout << "Killing another shared pointer\n";
    return 0;
} // ptr1 离开作用域,最后一个引用消失,资源被销毁
输出:
Resource acquired
Killing one shared pointer
Killing another shared pointer
Resource destroyed
重要区别:从裸指针独立创建多个 shared_ptr 的危险
下面示例看似相似,却会导致崩溃:
#include <iostream>
#include <memory>
class Resource { /* 同上 */ };
int main()
{
    Resource* res{ new Resource };
    std::shared_ptr<Resource> ptr1{ res };
    {
        std::shared_ptr<Resource> ptr2{ res }; // 直接从裸指针创建
        std::cout << "Killing one shared pointer\n";
    } // ptr2 离开作用域,误认为独占资源,提前释放
    std::cout << "Killing another shared pointer\n";
    return 0;
} // ptr1 再次释放同一资源 → 未定义行为(崩溃)
输出:
Resource acquired
Killing one shared pointer
Resource destroyed
Killing another shared pointer
Resource destroyed
根本原因:两个 std::shared_ptr 分别从同一裸指针独立创建,各自维护独立的控制块,引用计数互不知晓。
最佳实践:若需多个 std::shared_ptr 共享同一资源,必须通过拷贝现有 std::shared_ptr 来创建。
std::make_shared
与 std::make_unique 类似,std::make_shared(C++11 可用)推荐用于创建 std::shared_ptr:
#include <iostream>
#include <memory>
class Resource { /* 同上 */ };
int main()
{
    auto ptr1{ std::make_shared<Resource>() };
    {
        auto ptr2{ ptr1 }; // 正确拷贝,共享引用计数
        std::cout << "Killing one shared pointer\n";
    }
    std::cout << "Killing another shared pointer\n";
}
使用 `std::make_shared` 的好处:
- 语法简洁,类型安全;  
- 避免独立创建多个 `shared_ptr` 导致的问题;  
- **性能优势**:一次性分配资源对象与控制块内存,减少二次分配开销。
---
## 深入实现细节
- `std::unique_ptr` 内部仅需单个指针;  
- `std::shared_ptr` 内部保存**两个指针**:  
  1. 指向托管对象;  
  2. 指向**控制块**(动态分配,保存引用计数等元数据)。  
若通过裸指针构造多个 `shared_ptr`,每个实例都会独立创建控制块 → 重复释放。  
通过拷贝/赋值现有 `shared_ptr`,共享同一控制块,引用计数正确递增。
---
## 从 unique_ptr 转换
```cpp
std::unique_ptr<Resource> up{ std::make_unique<Resource>() };
std::shared_ptr<Resource> sp{ std::move(up) }; // 合法,资源转移
反之,**不能**将 `shared_ptr` 转为 `unique_ptr`,因为共享语义违背独占语义。  
若函数返回智能指针,建议返回 `std::unique_ptr`,调用方按需转为 `std::shared_ptr` 即可。
---
## 注意事项
- 若任一 `std::shared_ptr` 未被正确销毁(例如所属对象泄漏),资源亦无法释放;  
- C++17 及更早版本,`std::shared_ptr` 不支持 C 风格数组;C++20 起支持数组特化。
---
## 结论
`std::shared_ptr` 适用于**多指针共享资源**场景。  
资源的生命周期由**最后一个引用**的 `std::shared_ptr` 控制,确保在适当时机自动、安全地释放。
