reset后std::shared_ptr仍可调用成员函数?原因及裸指针情况分析
测试代码
// C++ program to demonstrate shared_ptr #include <iostream> #include <memory> class A { public: void show() { std::cout << "A::show()" << std::endl; } }; int main() { std::shared_ptr<A> p1(new A); std::cout << p1.get() << std::endl; p1->show(); std::shared_ptr<A> p2(p1); p2->show(); std::cout << p1.get() << std::endl; std::cout << p2.get() << std::endl; // Returns the number of shared_ptr objects // referring to the same managed object. std::cout << p1.use_count() << std::endl; std::cout << p2.use_count() << std::endl; // Relinquishes ownership of p1 on the object // and pointer becomes NULL p1.reset(); std::cout << p1.get() << std::endl; std::cout << p2.use_count() << std::endl; std::cout << p2.get() << std::endl; p1->show(); p2->show(); std::cout << p1.get() << std::endl; std::cout << p2.use_count() << std::endl; std::cout << p2.get() << std::endl; return 0; }
程序输出
0x24dc5ef1790 A::show() A::show() 0x24dc5ef1790 0x24dc5ef1790 2 2 0 1 0x24dc5ef1790 A::show() A::show() 0 1 0x24dc5ef1790
问题解答
为什么p1.reset()后调用p1->show()仍能输出结果?
首先要明确:这属于C++标准定义的未定义行为,并非语言的设计特性,只是当前环境下侥幸运行成功,原因有两点:
show()是非虚成员函数:这类函数的调用地址在编译阶段就已确定,不需要通过对象实例的虚表动态查找,编译后会直接生成调用A::show()的指令;show()没有访问类的成员变量,也没有使用隐式的this指针:即使p1是空指针,调用函数时传递的this指针是nullptr,但函数内部没有对this指针做任何解引用操作,所以不会触发非法内存访问,因此能正常输出字符串。
裸指针是否存在相同情况?
是的,裸指针也会出现这种现象。比如执行以下代码:
A* ptr = nullptr; ptr->show();
同样可能输出A::show(),但这同样是未定义行为——C++标准不保证这种情况一定能正常运行,在不同编译器、不同运行环境下,可能直接触发程序崩溃,或者出现其他不可预料的结果。
重要提醒:永远不要依赖这种未定义行为编写代码,空指针(无论智能指针还是裸指针)调用成员函数本身就是错误的写法,必须在调用前确保指针指向有效的对象实例。
内容的提问来源于stack exchange,提问作者subha
相关产品推荐
相关产品推荐

