‘assert(this)’是否为C++标准允许的可行代码模式?
关于C成员函数里
assert(this)的合规性与g行为解析 咱们直接切入核心问题,分两部分给你讲清楚:
一、这种写法符合C++标准吗?
答案是符合,但有明确的前提限制。
先掰扯C++标准里的规定:
- 当你用空指针调用非虚成员函数时,只要函数内部没去访问对象的非静态数据成员、没调用需要对象实体存在的其他成员函数,单纯读取
this指针的值(比如assert(this)只是判断它是否为空),这在标准里是允许的,不属于未定义行为。 - 但要注意:一旦你在函数里访问了
this指向的内容(比如代码里的std::cout << a << std::endl;,这里的a等价于this->a,属于解引用this),如果this是空指针,就触发了未定义行为——不过你的代码里是先断言this非空,再去访问a,所以只要断言生效,后面的访问就是安全的。 - 另外,如果把
method2改成虚函数,情况就完全不一样了:通过空指针调用虚函数本身就是未定义行为,因为虚函数调用需要读取对象的虚表指针,这一步直接会导致程序崩溃(比如段错误),根本走不到assert(this)那一步。
二、g++的这个运行行为是设计出来的,还是偶然?
这绝对是设计使然。
对于非虚成员函数,g在编译时会把成员函数转换成类似普通函数的形式,把this指针作为第一个隐式参数传递进去。所以当你用nullptr调用method2时,g就会把空指针作为this参数传给函数,这时候函数里的assert(this)自然会检测到空指针,触发断言失败——这完全是编译器按照既定逻辑生成代码的结果,不是偶然现象。
要是换成虚函数,g会生成先读取对象虚表指针的代码,空指针解引用这一步直接就会让程序挂掉,断言根本没机会执行,这也完全符合C标准里虚函数空指针调用属于未定义行为的要求。
最后啰嗦两句
虽然这种写法符合标准,但正如你说的,风格确实拉胯:
- 成员函数的前置条件(比如指针非空)本来就该由调用者来保证,把检查塞到成员函数里,违背了职责分离的原则。
- 万一后续把
method2改成虚函数,空指针调用时直接就触发未定义行为,断言完全起不到作用,相当于埋了个坑。
内容的提问来源于stack exchange,提问作者emacs drives me nuts
相关产品推荐
相关产品推荐

