std::shared_ptr
std::shared_ptr
是一种共享所有权的智能指针,允许多个 shared_ptr
实例共享对同一个对象的所有权。通过引用计数机制,管理资源的生命周期。
主要特性:
shared_ptr
可以指向同一个对象。shared_ptr
实例指向同一对象。shared_ptr
背后依赖一个控制块(Control Block),用于存储引用计数和指向实际对象的指针。控制块的主要内容包括:
shared_ptr
提供多种构造函数和赋值操作,以支持不同的使用场景。
shared_ptr
。shared_ptr
变为空。shared_ptr
变为空。#include
#include
class Test
{
public:
Test(int val) : value(val)
{
std::cout << "Test(int val) " << std::endl;
}
Test(Test &&)
{
std::cout << "Test moved\n";
}
~Test()
{
std::cout << "~Test() " << std::endl;
}
void show() const
{
std::cout << "Value: " << value << std::endl;
}
private:
int value;
};
int main()
{
// shared_ptr接受的是一个已经创建好的指针或者nullptr
std::shared_ptr<Test> ptr1(new Test(100)); // 不推荐
Test *t1 = new Test(100);
std::shared_ptr<Test> ptr2(t1); // 不推荐,原生指针和只能指针共同存在
// std::shared_ptr ptr2_ = t1; // 不推荐,这是隐式构造,而且shared_ptr也不支持 explicit shared_ptr( T* p) noexcept;
Test t2(100);
std::shared_ptr<Test> ptr3(&t2); // error, shared_ptr 默认使用 delete 释放资源,但 t2 是栈上的对象,不能 delete,
// 会导致 未定义行为(UB)(通常是程序崩溃)。
std::shared_ptr<Test> ptr4(); // 实际上是一个函数声明,不是初始化!可以用std::shared_ptr ptr4{};
std::shared_ptr<Test> ptr4_(nullptr);
// make_unique会调用T对应的构造函数
std::shared_ptr<Test> ptr5 = std::make_shared<Test>(100); // 推荐!
std::shared_ptr<Test> ptr5_ = ptr5; // 调用的是拷贝构造,会增加其引用计数
std::cout << "ptr5 use_count: " << ptr5.use_count() << std::endl;
/*
调用的是shared_ptr里面的operator bool()函数:
explicit operator bool() const noexcept
{
return get() != nullptr;
}
if (!ptr5) 等价于:if(!ptr5.operator bool())
*/
if (!ptr5)
{
std::cout << "ptr5 is now nullptr" << std::endl;
}
ptr5.reset(new Test(300)); //释放detele原资源(如果引用计数为0,否则引用计数-1)、接管新资源,是替换资源最干净、安全的方式。
ptr5.get()->show(); //借用原生指针
ptr5.reset(); //调用 delete 销毁这个对象(如果引用计数为0,否则引用计数-1),然后把内部的指针设为 nullptr,并不是销毁了ptr5
return 0;
}
输出:
Test(int val)
Test(int val)
Test(int val)
Test(int val)
ptr5 use_count: 2
Test(int val)
Value: 300
~Test()
~Test()
~Test()
SimpleSharedPtr
的完整实现及其使用示例。
#include
// 控制块结构
struct ControlBlock {
int ref_count;
ControlBlock() : ref_count(1) {}
};
// 简化版的 shared_ptr 实现
template <typename T>
class SimpleSharedPtr {
private:
T* ptr; // 指向管理的对象
ControlBlock* control; // 指向控制块
// 释放当前资源
void release() {
if (control) {
control->ref_count--;
std::cout << "Decremented ref_count to " << control->ref_count << std::endl;
if (control->ref_count == 0) {
delete ptr;
delete control;
std::cout << "Resource and ControlBlock destroyed." << std::endl;
}
}
ptr = nullptr;
control = nullptr;
}
public:
// 默认构造函数
SimpleSharedPtr() : ptr(nullptr), control(nullptr) {
std::cout << "Default constructed SimpleSharedPtr (nullptr)." << std::endl;
}
// 参数化构造函数
explicit SimpleSharedPtr(T* p) : ptr(p) {
if (p) {
control = new ControlBlock();
std::cout << "Constructed SimpleSharedPtr, ref_count = " << control->ref_count << std::endl;
} else {
control = nullptr;
}
}
// 拷贝构造函数
SimpleSharedPtr(const SimpleSharedPtr& other) : ptr(other.ptr), control(other.control) {
if (control) {
control->ref_count++;
std::cout << "Copied SimpleSharedPtr, ref_count = " << control->ref_count << std::endl;
}
}
// 拷贝赋值操作符
SimpleSharedPtr& operator=(const SimpleSharedPtr& other) {
if (this != &other) {
release();
ptr = other.ptr;
control = other.control;
if (control) {
control->ref_count++;
std::cout << "Assigned SimpleSharedPtr, ref_count = " << control->ref_count << std::endl;
}
}
return *this;
}
// 移动构造函数
SimpleSharedPtr(SimpleSharedPtr&& other) noexcept : ptr(other.ptr), control(other.control) {
other.ptr = nullptr;
other.control = nullptr;
std::cout << "Moved SimpleSharedPtr." << std::endl;
}
// 移动赋值操作符
SimpleSharedPtr& operator=(SimpleSharedPtr&& other) noexcept {
if (this != &other) {
release();
ptr = other.ptr;
control = other.control;
other.ptr = nullptr;
other.control = nullptr;
std::cout << "Move-assigned SimpleSharedPtr." << std::endl;
}
return *this;
}
// 析构函数
~SimpleSharedPtr() {
release();
}
// 解引用操作符
T& operator*() const {
return *ptr;
}
// 箭头操作符
T* operator->() const {
return ptr;
}
// 获取引用计数
int use_count() const {
return control ? control->ref_count : 0;
}
// 获取裸指针
T* get() const {
return ptr;
}
// 重置指针
void reset(T* p = nullptr) {
release();
ptr = p;
if (p) {
control = new ControlBlock();
std::cout << "Reset SimpleSharedPtr, ref_count = " << control->ref_count << std::endl;
} else {
control = nullptr;
}
}
};
// 测试类
class Test {
public:
Test(int val) : value(val) {
std::cout << "Test Constructor: " << value << std::endl;
}
~Test() {
std::cout << "Test Destructor: " << value << std::endl;
}
void show() const {
std::cout << "Value: " << value << std::endl;
}
private:
int value;
};
int main() {
std::cout << "Creating default constructed shared_ptr..." << std::endl;
SimpleSharedPtr<Test> ptr1; // 默认构造
std::cout << "ptr1 use_count: " << ptr1.use_count() << std::endl;
std::cout << "\nCreating shared_ptr with resource..." << std::endl;
SimpleSharedPtr<Test> ptr2(new Test(100)); // 非默认构造
std::cout << "ptr2 use_count: " << ptr2.use_count() << std::endl;
ptr2->show();
std::cout << "\nCopying ptr2 to ptr3..." << std::endl;
SimpleSharedPtr<Test> ptr3 = ptr2; // 拷贝构造
std::cout << "ptr2 use_count: " << ptr2.use_count() << std::endl;
std::cout << "ptr3 use_count: " << ptr3.use_count() << std::endl;
ptr3->show();
std::cout << "\nAssigning ptr3 to ptr1..." << std::endl;
ptr1 = ptr3; // 拷贝赋值
std::cout << "ptr1 use_count: " << ptr1.use_count() << std::endl;
std::cout << "ptr2 use_count: " << ptr2.use_count() << std::endl;
std::cout << "ptr3 use_count: " << ptr3.use_count() << std::endl;
std::cout << "\nResetting ptr2..." << std::endl;
ptr2.reset(new Test(200)); // 重新指向新的对象
std::cout << "ptr2 use_count: " << ptr2.use_count() << std::endl;
ptr2->show();
std::cout << "ptr1 use_count: " << ptr1.use_count() << std::endl;
std::cout << "ptr3 use_count: " << ptr3.use_count() << std::endl;
std::cout << "\nExiting scope..." << std::endl;
} // ptr2, ptr1, ptr3 离开作用域
std::cout << "End of main." << std::endl;
return 0;
}
它允许一个对象在 不自己持有自身的 shared_ptr
的情况下,获得一个指向自己的 shared_ptr
实例。
std::shared_ptr(this)
?看这个反面例子:
class MyClass {
public:
void doSomething() {
std::shared_ptr<MyClass> ptr(this); // ❌危险!会 double delete!
}
};
shared_ptr(this)
会产生一个新的 shared_ptr
实例,它并不知道有没有其他 shared_ptr
管理着这个对象。std::make_shared()
创建过一个,这里再来一次相当于有两个独立的 shared_ptr
,它们都会尝试在析构时删除这个对象,就爆炸了(double free)。enable_shared_from_this
#include
#include
class MyClass : public std::enable_shared_from_this<MyClass> {
public:
void doSomething() {
std::shared_ptr<MyClass> ptr = shared_from_this(); // 安全!
std::cout << "use_count: " << ptr.use_count() << std::endl;
}
};
int main() {
std::shared_ptr<MyClass> obj = std::make_shared<MyClass>();
obj->doSomething(); // ✅ 没问题
}
enable_shared_from_this
,并用 make_shared
构造对象时,enable_shared_from_this
内部会记录这个对象的 shared_ptr
。shared_from_this()
就能安全地返回一个新的 shared_ptr
指向自己,而不是重新创建一个。用途 | 作用 |
---|---|
std::enable_shared_from_this |
允许类内部通过 shared_from_this() 获取自身的 shared_ptr |
解决问题 | 避免 shared_ptr(this) 导致的 双重删除 / 崩溃 |
依赖前提 | 对象必须是由 shared_ptr 创建的,否则 shared_from_this() 会抛异常 |