成员函数调用过程中销毁对象是否属于未定义行为?
成员函数执行期间销毁对象的行为判定
问题场景
- 调用对象的成员函数(如
mystruct.method()) - 函数调用过程中触发对象销毁:例如对象由容器内的
std::shared_ptr持有,调用的函数移除了最后一个维持对象存活的shared_ptr - 成员函数执行流程中,对象的析构函数被调用,对象生命周期结束
很多人会担心:成员函数执行过程中对象已不存在,但仍处于函数执行流程中,这种情况的行为是否明确?
测试示例
有如下测试代码:
struct mystruct { void mymethod() { std::cerr << "in mymethod, calling f()\n"; f(); std::cerr << "in my method, after f()\n"; } std::function<void(void)> f; ~mystruct() { std::cerr << " ~~~ in mystruct dtor\n"; } }; std::set<std::shared_ptr<mystruct>> set; auto tmp = std::make_shared<mystruct>(); tmp->f = [&]() { set.clear(); std::cerr << "in lambda\n"; }; auto &ref = *tmp; set.insert(std::move(tmp)); ref.mymethod();
程序输出:
in mymethod, calling f() ~~~ in mystruct dtor in lambda in my method, after f()
行为判定
这个场景的行为是定义明确的,原因如下:
- 调用
mymethod()时,对象处于存活状态,调用成员变量f的行为合法。 - 在lambda执行
set.clear()时,最后一个shared_ptr被销毁,触发对象析构,此时对象生命周期结束。但lambda本身没有访问对象的任何非静态成员,只是操作外部的set并输出内容,这部分执行不受对象销毁的影响。 - 从lambda返回后,
mymethod()剩余的代码只是执行字符串输出,没有访问对象的任何成员或调用其他非静态成员函数,也不会解引用this指针,因此这部分执行也是合法的。
需要注意的是,如果在对象销毁后,成员函数仍尝试访问对象的非静态成员(比如读取成员变量、调用其他成员函数),那么这种行为属于未定义行为,此时即使valgrind或 sanitizers 没检测出问题,也不能保证程序行为的稳定性。
内容的提问来源于stack exchange,提问作者Daniel
相关产品推荐
相关产品推荐

