You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

空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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 02:20:38