代码之家  ›  专栏  ›  技术社区  ›  Yksisarvinen

是否通过统一化指针访问静态类成员?

  •  1
  • Yksisarvinen  · 技术社区  · 5 年前

    后续问题 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 回复  |  直到 5 年前
        1
  •  10
  •   Brian Bi    5 年前

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

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

    还有一个脚注说:

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

    在本例中,表达式 *a 进行了评估。自从 a 是一个尚未初始化的自动变量,[dcl.init]/12适用于:

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

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