c ++:为什么'this'不能成为nullptr?

use*_*001 2 c++ this nullptr

在我使用C++的早期,我似乎记得你可以使用NULL指针调用成员函数,并在成员函数中检查它:

class Thing {public: void x();}

void Thing::x()
{ if (this == NULL) return; //nothing to do
   ...do stuff...
}

Thing* p = NULL; //nullptr these days, of course
p->x(); //no crash
Run Code Online (Sandbox Code Playgroud)

这样做可能看起来很愚蠢,但是当编写递归函数来遍历数据结构时,这绝对是很棒的,导航很容易进入NULL的盲道; 导航功能可以在顶部对NULL进行单一检查,然后轻松地调用自己尝试深入导航而不会乱丢代码并进行额外检查.

至少根据g ++,自由(如果它曾经存在)已被撤销.编译器警告它,如果编译优化,它会导致崩溃.

问题1:C++标准(任何风格)是否禁止使用NULL?或者g ++只是在我面前?

问题2.更哲学,为什么?'这'只是另一个指针.指针的荣耀在于它们可以是nullptr,这是一个有用的条件.

我知道我可以通过创建静态函数来解决这个问题,将第一个参数传递给数据结构的指针(hellllo Days of C),然后检查指针.我很惊讶我需要.

编辑:为了提出答案,我希望看到关于为什么不允许这样做的标准的章节和经文.请注意,我在NO POINT处的示例取消引用NULL.这里没有什么是虚拟的,并且p被复制到"参数this"但在使用之前被检查.没有任何差别!因此,取消引用NULL不能用作UB的声明.

人们对*p做出了下意识的反应,并假设如果p为NULL则无效.但确实如此,证据就在这里:http: //www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#232 事实上,当一个指针p令人惊讶时,它会调出两个案例有效为*p:当p为null或p指向一个元素超过数组末尾时.你必须做的就是使用*p的值......除了获取它的地址.&*p其中p == nullptr表示任何指针类型p都有效.可以指出p-> x()实际上是(*p).x(),但在一天结束时转换为x(&*p)并且形成得非常好且有效.对于p = nullptr ...它只是变成x(nullptr).

我认为我的辩论应该与标准界有关; 他们急于削弱空引用的概念,他们的措辞不清楚.因为这里没有人要求p-> x()是UB而不试图要求它是UB,因为*p是UB; 并且因为*p绝对不是UB,因为x()的任何方面都没有使用引用的值,我将把它归结为g ++对标准歧义的超越.使用静态函数和额外参数的绝对相同的机制已经很好地定义了,所以它不会停止我的重构工作.考虑撤回的问题; 可移植代码不能假设这个== nullptr会工作但是有一个可移植的解决方案,所以最后它没关系.

Fra*_*eux 8

处于这样一种情况,thisnullptr暗示你调用非静态成员函数而不使用有效实例,例如指针设置为nullptr.由于这是禁止的,要获得null,this您必须已经处于未定义的行为.换句话说,除非你有未定义的行为,否则this永远不会nullptr.由于未定义行为的性质,您可以将语句简化为" this永远不会nullptr",因为在存在未定义行为时不需要维护规则.

  • @ user15001根据标准中的**[expr.ref]**(根据N4594检查),`p-> x`和`(*(p)).x`必须具有相同的行为.第二种显然是在这种情况下取​​消引用空指针并且是坏的,所以为了具有相同的行为,第一种情况也必须是坏的. (3认同)

Jer*_*ner 5

问题 1:C++ 标准(任何风格)是否不允许 NULL this?或者g++只是挡在我面前?

C++ 标准不允许这样做——在 NULL 指针上调用方法是正式的“未定义行为”,您必须避免这样做,否则您会受到影响。特别是,优化器在进行优化时会假设 this 指针为非 NULL,从而导致运行时出现奇怪/意外的行为(我从经验中知道这一点:))

问题 2. 从哲学角度来说,为什么?“this”只是另一个指针。指针的优点在于它们可以为 nullptr,这是一个有用的条件。

我不确定这是否重要,真的;这是 C++ 标准中指定的,他们可能有他们的原因(哲学或其他),但由于标准指定了它,编译器期望它,因此作为程序员我们必须遵守它,否则将面临未定义的行为。(人们可以想象另一个宇宙,其中允许 NULL this 指针,但我们不住在那里)