shared_from_this() 要求对象必须由 shared_ptr 管理,而不能是普通的栈对象。
核心原理
1. enable_shared_from_this 的内部机制
std::enable_shared_from_this 模板类内部维护了一个 weak_ptr 成员变量:
template<class T>
class enable_shared_from_this {
private:
mutable weak_ptr<T> __weak_this_; // 内部维护的 weak_ptr
public:
shared_ptr<T> shared_from_this() {
return shared_ptr<T>(__weak_this_); // 从 weak_ptr 构造 shared_ptr
}
// ... 其他成员
};
2. shared_ptr 构造过程中的关键步骤
当使用 std::make_shared<T> 或 std::shared_ptr<T>(new T) 创建对象时,shared_ptr 的构造函数会执行以下关键操作:
// 简化的 shared_ptr 构造函数逻辑
template<typename T>
shared_ptr<T>::shared_ptr(T* ptr) {
// 1. 创建控制块(存储引用计数等)
control_block = new ControlBlock();
// 2. 如果 T 继承自 enable_shared_from_this<T>
if constexpr (std::is_base_of_v<std::enable_shared_from_this<T>, T>) {
// 3. 设置 enable_shared_from_this 内部的 weak_ptr
ptr->__weak_this_ = *this; // 将内部的 weak_ptr 指向当前 shared_ptr
}
}
为什么栈对象不行?
1. 控制块缺失
栈对象没有关联的控制块(control block),而控制块是管理引用计数和弱计数的核心:
栈对象:
[对象数据]
^
|
栈指针
shared_ptr 管理的对象:
[控制块] -----> [对象数据]
^ ^
| |
shared_ptr shared_ptr
2. weak_ptr 无法正确初始化
对于栈对象,enable_shared_from_this 内部的 __weak_this_ 成员变量永远不会被正确初始化,因为它没有对应的 shared_ptr 来设置它。
3. 生命周期管理冲突
栈对象遵循自动生命周期管理(超出作用域自动销毁),而 shared_ptr 使用引用计数机制。这两种生命周期管理方式存在根本性冲突。
深入原理:具体示例分析
正确用法示例
class MyClass : public std::enable_shared_from_this<MyClass> {
public:
std::shared_ptr<MyClass> get_shared() {
return shared_from_this();
}
};
int main() {
// 正确:对象由 shared_ptr 管理
auto obj = std::make_shared<MyClass>();
auto shared_copy = obj->get_shared(); // 正常工作
return 0;
}
在这个例子中:
std::make_shared<MyClass>()创建对象和控制块shared_ptr构造函数检测到MyClass继承自enable_shared_from_this- 设置
MyClass::__weak_this_指向新创建的shared_ptr shared_from_this()可以从__weak_this_成功创建新的shared_ptr
错误用法示例
int main() {
// 错误:栈对象
MyClass obj;
try {
auto shared = obj.get_shared(); // 抛出 bad_weak_ptr
} catch (const std::bad_weak_ptr& e) {
// 因为 obj.__weak_this_ 从未被正确初始化
}
return 0;
}
底层实现细节
shared_ptr 的控制块结构
控制块结构:
[use_count] // 强引用计数
[weak_count] // 弱引用计数
[deleter] // 删除器
[allocator] // 分配器
enable_shared_from_this 的完整实现机制
实际上,shared_ptr 构造函数中设置 __weak_this_ 的代码类似于:
template<typename T>
void shared_ptr<T>::_Enable_shared_from_this(const std::enable_shared_from_this<T>* esft) const {
if (esft != nullptr) {
esft->__weak_this_ = std::shared_ptr<T>(*this,
const_cast<std::remove_cv_t<T>*>(static_cast<const T*>(esft)));
}
}
总结:为什么必须使用 shared_ptr
- 控制块需求:
weak_ptr需要依赖shared_ptr的控制块来跟踪对象生命周期 - 初始化机制:只有
shared_ptr构造函数能正确初始化enable_shared_from_this内部的weak_ptr - 生命周期一致性:确保所有
shared_ptr实例使用相同的生命周期管理机制 - 线程安全:
shared_ptr的控制块提供了线程安全的引用计数操作
这就是为什么使用 shared_from_this() 时必须确保对象是由 shared_ptr 管理,而不能是普通栈对象的根本原因。这种设计保证了对象生命周期管理的一致性和安全性,避免了悬空指针和内存管理错误。

被折叠的 条评论
为什么被折叠?



