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
答案 0 :(得分:10)
a->n
的语义是*a
被评估但未被访问,因为数据成员是静态的。参见C ++ 17 [expr.ref]:
...计算点或箭头之前的后缀表达式...表达式
E1->E2
转换为等效形式(*(E1)).E2
...
还有一个脚注:
如果评估了类成员访问表达式,则即使不需要确定整个后缀表达式的值(例如,如果id表达式表示静态成员),也将进行子表达式评估。
在这种情况下,表达式*a
被求值。由于a
是尚未初始化的自动变量,因此适用[dcl.init] / 12:
如果评估产生不确定的值,则该行为是不确定的,除了以下情况:[...]
评估*a
显然需要访问指针变量a
的值,该值是不确定的值,因此它是UB。