在C++的面向对象编程和智能指针使用场景中,有时我们需要在类的成员函数内部获取当前对象对应的shared_ptr实例,比如把当前对象作为参数传递给其他需要shared_ptr的函数,或者将自身存入容器。如果直接通过this指针构造shared_ptr,会创建新的控制块,导致同一个对象被多个独立的shared_ptr管理,最终触发重复释放的未定义行为。enable_shared_from_this就是标准库为解决这个问题提供的方案,它定义在memory头文件中,是一个模板基类。

enable_shared_from_this的基本用法
要使用enable_shared_from_this,需要让自定义类公有继承enable_shared_from_this模板类,模板参数为自定义类本身,然后在需要获取自身shared_ptr的地方调用shared_from_this()成员函数。
下面是一个简单的基础使用示例:
#include <iostream>
#include <memory>
// 自定义类继承enable_shared_from_this,模板参数为自身类型
class MyClass : public std::enable_shared_from_this<MyClass> {
public:
MyClass() {
std::cout << "MyClass构造函数执行" << std::endl;
}
~MyClass() {
std::cout << "MyClass析构函数执行" << std::endl;
}
// 成员函数,返回自身的shared_ptr
std::shared_ptr<MyClass> getSelfPtr() {
return shared_from_this();
}
void printInfo() {
std::cout << "这是MyClass的实例" << std::endl;
}
};
int main() {
// 必须通过shared_ptr管理对象,不能直接用new构造裸指针
std::shared_ptr<MyClass> obj = std::make_shared<MyClass>();
// 调用成员函数获取自身的shared_ptr
std::shared_ptr<MyClass> selfPtr = obj->getSelfPtr();
// 验证两个shared_ptr指向同一个对象
std::cout << "obj引用计数: " << obj.use_count() << std::endl;
std::cout << "selfPtr引用计数: " << selfPtr.use_count() << std::endl;
selfPtr->printInfo();
return 0;
}
上述代码运行后,obj和selfPtr的引用计数都会是2,说明它们共享同一个控制块,对象只会被析构一次,不会出现重复释放的问题。
enable_shared_from_this的实现原理
enable_shared_from_this的核心实现依赖于weak_ptr,它的内部通常维护了一个weak_ptr<T>类型的成员变量,这个弱引用指向当前对象。
当用shared_ptr管理继承enable_shared_from_this的对象时,shared_ptr的构造函数会检测到对象继承自enable_shared_from_this,然后将内部的弱引用成员初始化为指向当前对象的弱引用。之后调用shared_from_this()时,会把这个弱引用升级为shared_ptr返回,这样就保证了返回的shared_ptr和原有的shared_ptr共享同一个控制块。
我们可以用简化的伪代码表示它的核心逻辑:
// 简化的enable_shared_from_this实现逻辑
template <typename T>
class enable_shared_from_this {
private:
mutable std::weak_ptr<T> weak_this; // 内部维护的弱引用成员
protected:
enable_shared_from_this() noexcept = default;
enable_shared_from_this(const enable_shared_from_this&) noexcept {}
enable_shared_from_this& operator=(const enable_shared_from_this&) noexcept { return *this; }
public:
std::shared_ptr<T> shared_from_this() {
// 把弱引用升级为shared_ptr,如果对象已经被释放会抛出异常
return std::shared_ptr<T>(weak_this);
}
std::shared_ptr<T const> shared_from_this() const {
return std::shared_ptr<T const>(weak_this);
}
// 供shared_ptr内部调用的初始化函数,用于设置weak_this
void internal_init(std::shared_ptr<T>* p) const {
if (weak_this.expired()) {
weak_this = std::weak_ptr<T>(*p);
}
}
};
使用enable_shared_from_this的注意事项
必须通过shared_ptr管理对象
如果对象不是由shared_ptr管理的,直接调用shared_from_this()会导致未定义行为,通常会抛出异常或者程序崩溃。因为此时内部的弱引用成员没有被正确初始化,是空的。
下面是错误的用法示例:
#include <iostream>
#include <memory>
class BadClass : public std::enable_shared_from_this<BadClass> {
public:
void test() {
// 错误:对象不是由shared_ptr管理,调用shared_from_this()会出错
auto self = shared_from_this();
}
};
int main() {
// 错误:直接构造裸指针对象,没有用shared_ptr管理
BadClass obj;
obj.test();
return 0;
}
不要在构造函数中调用shared_from_this()
对象的构造过程中,shared_ptr还没有完成对weak_this的初始化,此时调用shared_from_this()会因为弱引用为空而失败。因为shared_ptr的初始化是在对象构造完成之后才进行的。
避免循环引用问题
虽然enable_shared_from_this本身不会导致循环引用,但如果使用不当,比如两个对象互相通过shared_from_this()持有对方的shared_ptr,就会形成循环引用,导致对象无法释放。这种情况下需要把其中一个引用改为weak_ptr来打破循环。
常见错误用法对比
下面通过表格对比几种常见的错误用法和正确用法:
| 场景 | 错误用法 | 正确用法 |
|---|---|---|
| 获取自身shared_ptr | return std::shared_ptr<MyClass>(this); | return shared_from_this(); |
| 对象创建方式 | MyClass* obj = new MyClass(); | auto obj = std::make_shared<MyClass>(); |
| 构造函数内获取自身引用 | 在构造函数中调用shared_from_this() | 在构造函数之外的成员函数中调用 |
适用场景总结
enable_shared_from_this适用于以下场景:
- 类的成员函数需要把当前对象传递给其他需要shared_ptr参数的函数
- 需要把当前对象存入需要shared_ptr的容器,比如std::vector<std::shared_ptr<T>>
- 在异步回调中需要持有当前对象的引用,避免对象在回调执行前被释放
只要遵循正确的使用规则,enable_shared_from_this就能安全地帮助我们在类内部获取自身的shared_ptr引用,避免内存管理相关的错误。
C++enable_shared_from_thisshared_ptr弱引用对象生命周期管理修改时间:2026-07-18 18:12:40