持有C++对象成员函数的shared_ptr时,对象析构函数是否会被调用?
首先明确:objectA的析构函数是否被调用,完全取决于MyClass::getFuncPointer()内部如何构造并返回std::function<void()>,分两种核心场景分析:
场景1:析构函数不会被调用
如果getFuncPointer()内部通过std::enable_shared_from_this获取自身的shared_ptr,并将其捕获到std::function中,比如实现如下:
class MyClass : public std::enable_shared_from_this<MyClass> { public: void func() {} std::shared_ptr<std::function<void()>> getFuncPointer() { auto self = shared_from_this(); return std::make_shared<std::function<void()>>([self]() { self->func(); }); } };
此时std::function内部持有了objectA的shared_ptr,当objectB保存这个返回值后,objectA的引用计数会从1(仅objectB持有)变为2(objectB+std::function内部的self)。
当objectB调用objectA.reset()后,objectA的引用计数降为1,并未归零,因此析构函数不会被调用。这种情况下不存在“对象已销毁但函数还在执行”的问题,因为std::function持有的shared_ptr会保证对象存活到std::function本身被销毁为止。
场景2:析构函数会被调用
如果getFuncPointer()只是简单绑定成员函数的原始指针,没有捕获objectA的shared_ptr,比如实现如下:
std::shared_ptr<std::function<void()>> MyClass::getFuncPointer() { return std::make_shared<std::function<void()>>(std::bind(&MyClass::func, this)); }
这里std::bind仅捕获了原始指针this,并未持有objectA的shared_ptr。此时objectA的引用计数仅由objectB的shared_ptr维护,当objectB调用reset()后,引用计数归零,析构函数会立即被调用。
如果此时其他线程通过保存的std::function调用func(),就会访问已经被销毁的对象成员,这属于未定义行为——程序可能崩溃、出现乱码数据,或者表现出其他不可预测的结果,绝对要避免这种情况。
对两种疑问的回应
- 你担心的“对象析构后函数仍在执行”的问题,只会出现在第二种场景中,本质是因为
std::function没有持有对象的智能指针,无法保证对象生命周期; - 你疑惑的“函数指针如何让对象存活”,实际并非函数指针本身,而是
std::function内部捕获的shared_ptr延长了对象的生命周期,这是符合智能指针设计逻辑的。
内容的提问来源于stack exchange,提问作者Fuad

