在成员函数中测试this-pointer是合法的C++吗?

use*_*486 4 c++ null this

我有一个涉及不同类类型的对象的应用程序.对象由指针引用.空指针表示关联的对象不存在.目前,调用代码很麻烦,因为每次使用指向对象的指针时,它都会测试指针值为null,并采取一些适当的操作,它为null.因为在不存在的情况下要采取的默认操作取决于对象的类型,我宁愿在对象本身的类中而不是在调用程序中对其进行编码.这导致如下构造:

class C
{ ... 
  void member_func() //non-virtual !
  { if (this) { do something with the object ... }
    else { take some default action }
  }
  ...
};
Run Code Online (Sandbox Code Playgroud)

显然,成员函数不能是虚拟的,因为当对象不存在时查找表不存在,并且虚拟调用将失败.但这个代码是否适用于非虚拟成员函数的合法C++?它似乎对我尝试过的编译器工作正常,但我担心可能的不可移植性.在标准中,我找不到明确允许或明确禁止此类结构的条款.

izo*_*ica 12

this 在成员函数中永远不会为null,因此您执行的检查是无用的.

正如Matthieu M.在评论中指出的那样,如果你在代码中做了类似的事情:

C* c = 0; 
c->member();
Run Code Online (Sandbox Code Playgroud)

这会导致未定义的行为,这是不好的.

  • @Useless:重点在于*在一个程序中,其行为是未定义的*只是因为`this == NULL`计算结果为true,而'this`"为"null"并不真正有意义.在这一推论上你可能会编写一些代码(在某些实现中)使一个值看起来"成为"两个不同的东西.没有什么是真的,一切都是允许的,就像一个有趣的斗篷中的家伙曾经告诉我的那样.*在没有UB*的程序中,`this`不为空,并且不言而喻,关于程序行为的全面陈述仅适用于其行为已定义的程序. (4认同)
  • 或者更确切地说,如果你做`X*x = 0; x-> member();`然后你调用**Undefined Behavior**并且所有的赌注都关闭了. (3认同)

Ben*_*ley 6

正如已经指出的那样,this永远不能是空指针.如果是,您已经调用了未定义的行为.相反,您可以创建一组重载函数,如下所示:

void DoTheThing(C* cp)
{
    if (cp)
        cp->member_func();
    else
    {
        // take some default action
    }
}

void DoTheThing(B* bp)
{
    if (bp)
        bp->some_other_member_func();
    else
    {
        // take some default action
    }
}
Run Code Online (Sandbox Code Playgroud)

如果要调用的函数在每个类中具有相同的名称,那么您可以在每个类中创建一个静态函数,该函数执行该类的默认操作(都具有相同的名称),并创建一个模板:

template<typname T>
void DoTheThing(T* tp)
{
    if (tp)
        tp->member_func();
    else
        T::default_action()
}
Run Code Online (Sandbox Code Playgroud)

  • 它是未定义的行为,因为标准没有规定函数调用机制.例如,假设通过空指针进行虚拟调用是不可能的.对于非虚拟调用,我认为没有任何实际原因**需要*为UB而不是使用`this`调用空指针.但就像Benjamin说它只是UB一样,标准说你不能取消引用空指针."`this`是一个隐藏的第一个参数"是一个类比来解释被调用代码如何知道它被调用的对象,它不是`this`的定义. (4认同)
  • @ user1958486:[5.2.5/2]*表达式E1-> E2被转换为等价形式(*(E1)).E2* - 因此,它确实涉及空指针的解除引用. (3认同)