C++ 它是否合法/定义明确的C++;调用不使用';是否无法通过空指针访问成员?

C++ 它是否合法/定义明确的C++;调用不使用';是否无法通过空指针访问成员?,c++,pointers,null,methods,standards,C++,Pointers,Null,Methods,Standards,我最近遇到了以下代码: class Foo { public: void bar(); // .. other stuff }; void Foo::bar() { if(!this) { // .. do some stuff without accessing any data members return; } // .. do normal actions using data members } >代码编译

我最近遇到了以下代码:

class Foo
{
public:
    void bar();
    // .. other stuff
};

void Foo::bar()
{
    if(!this) {
        // .. do some stuff without accessing any data members
        return;
    }

    // .. do normal actions using data members
}
<> >代码编译,因为C++方法只是隐式传递的函数,这个“this”和“this”可以被检查为null,就像任何其他指针一样。很明显,这段代码令人困惑,而且是糟糕的做法,即使它没有崩溃;在调试器中一步一步地遍历代码会非常混乱,看到一个空指针即将调用一个方法,但没有看到预期的崩溃。我的问题是:它违反C++标准调用<代码>某个Fopopt> Bar()/Case>代码< > FooptR==null < /C> > /P>
我觉得这可能不是因为用户定义的操作符->返回一个指针,这意味着即使该指针为NULL,它也肯定没有被取消引用(我确信,取消引用NULL指针被标准视为非法或未定义)。另一方面,原始指针的语义不一定要与用户定义指针的语义相匹配——也许它们上的运算符->被认为是一种去引用,即使编译器不会生成一个去引用。

它是否合法并不重要,读者会感到困惑。在该代码工作的实现中,vtable是按类型访问的,当然不是按对象访问的


此外,我希望这段代码是为了掩盖构造函数失败,这将掩盖其他地方的各种问题。构造函数失败应该得到正确的处理,而不是像示例中那样使用令人讨厌的乱七八糟的行为。

这是(现在所有这些)未定义的行为。但是,对于许多编译器来说,它可以工作,但附加的限制是该方法必须是非虚拟的。

它是UB。使其崩溃的一个好方法是将其用作使用多重继承的派生类的基类。YMMV.

这可能适用于大多数系统,但它是未定义的行为。引用标准:

5.2.5.3

如果
E1
具有“指向类X的指针”类型,则表达式
E1->E2
将转换为等效形式
(*(E1))。E2
[…]

以及:

5.2.5.1

后缀表达式后跟点
或箭头
->
,可选地后跟关键字
模板
(14.8.1),然后后跟id表达式,是后缀表达式。计算点或箭头之前的后缀表达式;58)[……]

58)即使结果不需要确定整个后缀表达式的值(例如,如果id表达式表示静态成员),也会进行此计算


*x
进行评估,其中
x
为空指针,会导致未定义的行为,因此在函数输入之前,您的行为显然是UB。

即使取消引用不是UB,此测试也会失败。当多重继承的调整开始发挥作用时,它就会中断:

#include <stdio.h>
class B
{
    int value;
    public:
    void foo()
    {
        if (!this)
            printf("this==0\n");
        else 
            printf("safe\n");
    }
};
class A { public: int anotherValue; };
class Z : public A,public B {};

int main()
{
    Z *z=0;
    z->foo();
}
#包括
B类
{
int值;
公众:
void foo()
{
如果(!这个)
printf(“this==0\n”);
其他的
printf(“safe\n”);
}
};
A类{public:int-anotherValue;};
Z类:公共A,公共B{};
int main()
{
Z*Z=0;
z->foo();
}

在这里打印“安全”。

谢谢,这正是我要找的。抱歉,编辑太乱了。首先我忽略了标准中的一些内容,然后我误解了你的问题。现在应该可以了。你能举一个
A.template B
形式的表达式的例子吗?这个语法与什么有关?@Philip:假设你在一个模板类中编写代码,这个模板类接受一个T。然后在这个类中,你创建了一个其他类的对象。然后发现一些其他类有一个模板成员函数foo。某些x类;x、 模板foo();。基本上,当您将一个模板参数输入到另一个模板中时,如果后一个模板本身有一个模板成员,那么在访问它时,您必须将额外的template关键字放在那里,以免混淆解析器。至少我认为是这样。我现在凭直觉这么做,所以我可能描述得不完全正确。@Philipp:真是巧合,我几分钟前才学会这个语法!此处:副本: