通过统一指针UB访问静态类成员吗?

时间:2019-11-17 22:05:51

标签: c++ static language-lawyer undefined-behavior

this one的后续问题

我们有以下代码:

#include <iostream>

struct A 
{
    static int n;
};

int A::n = 5;

int main() 
{
    A* a; //uninitialized on purpose
    std::cout << a->n; //UB?
}

这样的访问是否具有不确定的行为?一方面,不需要对象来访问静态类成员,另一方面,未初始化指针上的operator->带来了麻烦。

注意:GCC和MSVC会在没有任何警告的情况下编译此代码,Clang抱怨未初始化的用法。 https://godbolt.org/z/Gy5fR2

1 个答案:

答案 0 :(得分:10)

a->n的语义是*a被评估但未被访问,因为数据成员是静态的。参见C ++ 17 [expr.ref]:

  

...计算点或箭头之前的后缀表达式...表达式   E1->E2转换为等效形式(*(E1)).E2 ...

还有一个脚注:

  

如果评估了类成员访问表达式,则即使不需要确定整个后缀表达式的值(例如,如果id表达式表示静态成员),也将进行子表达式评估。

在这种情况下,表达式*a被求值。由于a是尚未初始化的自动变量,因此适用[dcl.init] / 12:

  

如果评估产生不确定的值,则该行为是不确定的,除了以下情况:[...]

评估*a显然需要访问指针变量a的值,该值是不确定的值,因此它是UB。