首页 > 解决方案 > 是否通过未初始化的指针 UB 访问静态类成员?

问题描述

这个问题的后续问题

我们有以下代码:

#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

标签: c++staticlanguage-lawyerundefined-behavior

解决方案


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

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

还有一个脚注说:

如果评估类成员访问表达式,则即使结果对于确定整个后缀表达式的值不是必需的,例如如果 id-expression 表示静态成员,也会发生子表达式评估。

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

如果评估产生不确定的值,则行为未定义,但以下情况除外: [ ... ]

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


推荐阅读