代码之家  ›  专栏  ›  技术社区  ›  Joseph Garvin

是合法的/定义良好的C++调用非静态方法,它不通过空指针访问成员吗?

  •  7
  • Joseph Garvin  · 技术社区  · 14 年前

    我最近遇到了以下代码:

    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
    }
    

    SomeFooPtr->bar() 哪里 SomeFooPtr == NULL ?

    我突然想到,这可能不是因为用户定义的运算符->返回一个指针,这意味着即使该指针为空,它也肯定没有被取消引用(取消引用空指针我确信被标准视为非法或未定义)。另一方面,原始指针的语义不一定要与用户定义指针的语义相匹配——可能是运算符->即使编译器不会生成一个解引用,也会将其视为解引用。

    5 回复  |  直到 14 年前
        1
  •  13
  •   Thomas    14 年前

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

    如果 E1 E1->E2 转换为等效形式 (*(E1)).E2 [...]

    后跟点的后缀表达式 . 或者一支箭 -> ,可选择后跟关键字 template (14.8.1),然后是 ,是后缀表达式。计算点或箭头之前的后缀表达式; 58)

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

    *x 哪里 x

        2
  •  7
  •   Nordic Mainframe    14 年前

    即使取消引用不是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();
    }
    

        3
  •  1
  •   JSBÕ±Õ¸Õ£Õ¹    14 年前

    这是(现在一起) 未定义的行为 . 但是,对于许多编译器来说,它可以工作,并且附加了一个约束,即方法必须是非虚拟的。

        4
  •  1
  •   Hans Passant    14 年前

        5
  •  1
  •   msw    14 年前

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