空std::unique_ptr调用成员函数为何表现不同?是否符合预期?
空std::unique_ptr调用无成员访问的成员函数未触发段错误是否符合预期?
问题代码
class Demo { public: Demo() {} void noSegFault() { std::cout << "noSegFault" << std::endl; } void segFault() { std::cout << "Address of data :" << &data << std::endl; std::cout << "Before segfault" << std::endl; data = 234; std::cout << "After segfault" << std::endl; } private: int data{123}; }; int main() { std::unique_ptr<Demo> demoPtr{nullptr}; if (demoPtr == nullptr) { std::cout << "demoPtr is null" << std::endl; } demoPtr->noSegFault(); demoPtr->segFault(); return 0; }
程序输出
demoPtr is null noSegFault Address of data :0 Before segfault
问题
在此场景中,demoPtr被初始化为nullptr。原本以为访问nullptr必然会导致段错误,但程序中可以成功调用noSegFault()方法并看到输出,而调用访问成员变量的segFault()方法时则触发段错误。请问调用不访问成员变量的方法无段错误是否属于预期行为?
解答
这种行为本质上属于未定义行为,但实际运行中出现调用无成员访问的方法不触发段错误是常见现象,原因如下:
- 非虚成员函数的调用地址在编译阶段就已确定,不需要通过对象指针(
this指针)来动态查找函数地址。 - 调用
noSegFault()时,虽然传入的this指针是nullptr,但函数内部既没有访问任何成员变量,也没有使用this指针执行有效操作,因此不会触发内存访问错误。 - 而
segFault()中访问了成员变量data,此时需要通过this指针计算成员的内存地址(data的地址为this指针值加上成员的内存偏移量),当this是nullptr时,计算出的地址为0,对0地址执行写入操作就会触发段错误。
需要明确:即便本次调用未崩溃,也绝对不能依赖这种行为——C++标准明确规定通过空指针调用成员函数属于未定义行为,编译器可以做出任何处理(包括崩溃、正常运行甚至执行异常代码)。
内容的提问来源于stack exchange,提问作者goodman
相关产品推荐
相关产品推荐

