C++中调用未初始化shared_ptr的成员函数为何未触发段错误?
我运行了两段C++代码,第一段中未初始化的std::shared_ptr<AAA>调用成员函数show(),输出“Foo”且未崩溃;第二段给AAA类添加私有成员变量mData后,同样调用未初始化shared_ptr的show(),输出“Foo”后触发段错误。以下是具体代码和运行结果:
第一段代码
#include <memory> #include <iostream> class AAA { public: AAA(void) { std::cout<<"Ctor"<<std::endl; } void show() { std::cout<<"Foo"<<std::endl; } }; int main(void) { std::shared_ptr<AAA> a; // uninitialized a->show(); return 0; }
运行结果:
Foo
第二段代码
#include <memory> #include <iostream> class AAA { public: AAA(void) { std::cout<<"Ctor"<<std::endl; } void show() { std::cout<<"Foo"<<std::endl; std::cout<<mData; } private: int mData; }; int main(void) { std::shared_ptr<AAA> a; a->show(); return 0; }
运行结果:
Foo Segmentation fault (core dumped)
原因解析
第一段代码未崩溃的缘由
未初始化的std::shared_ptr<AAA>内部存储的是空指针,调用a->show()时,C++对非虚成员函数的处理逻辑是:将调用转换为类似AAA::show(a.get())的形式,这里的空指针会作为this参数传递给show函数。
但第一段的show()函数没有访问任何类成员变量,也没有使用this指针执行任何需要有效内存地址的操作——它只是单纯输出字符串,完全不依赖this指向的对象内存。这种情况下,程序侥幸完成了函数执行,没有触发内存错误。不过这属于未定义行为,C++标准不保证这种情况一定能正常运行,换用不同编译器或平台可能直接崩溃。
第二段代码触发段错误的原因
当AAA类添加成员变量mData后,show()函数中尝试访问mData:
- 访问类成员变量的本质是通过
this指针加上固定偏移量来定位内存地址(这里mData是第一个非静态成员,偏移量为0)。 - 此时
this是空指针,计算出的内存地址是无效的(空指针指向的内存区域不允许程序访问),尝试读取该地址的内容会直接触发操作系统的内存保护机制,导致段错误。
总结
两种情况本质都是未定义行为——使用空指针调用成员函数在C++标准中没有合法语义。第一段只是恰好函数逻辑没用到this指向的对象内存,才没触发崩溃;第二段因为访问了成员变量,必须通过空指针访问无效内存,所以直接触发段错误。
内容的提问来源于stack exchange,提问作者demonic3540
相关产品推荐
相关产品推荐

