编译器将表达式a->i替换为常量1是否合法?是否因a未被odr-used?
解答:
nullptr访问静态成员时a未被odr-used的说法是否正确? 首先看这段可跨GCC、clang和VS2017正常编译的代码:
struct A { static const int i = 1; }; int f() { A *a = nullptr; return a->i; }
你的问题是:认为这段代码合法的原因是a在表达式a->i中未被odr-used,这个说法是否正确?
答案是:完全正确。
我们可以结合C++标准的规则来拆解原因:
根据标准中关于odr-used的定义([basic.def.odr]/4):
A variable
xwhose name appears as a potentially-evaluated expressionexis odr-used byexunless applying the lvalue-to-rvalue conversion (7.1) toxyields a constant expression (8.6) that does not invoke any non-trivial functions and, ifxis an object,exis an element of the set of potential results of an expressione, where either the lvalue-to-rvalue conversion (7.1) is applied toe, oreis a discarded-value expression (8.2).
具体到这个场景:
- 表达式
a->i本质等价于A::i——因为i是类的静态成员,编译器只需要通过a的类型(A*)来定位要访问的静态成员,并不会真的去解引用a这个空指针。 - 按照[basic.def.odr]/2 (2.3)的规则,
a属于表达式a->i的潜在结果集元素,而对a->i应用左值到右值转换后,得到的是常量1,完全满足上述规则中的“除非”例外条件。
这就意味着a并没有被odr-used,所以即使它是nullptr,代码依然合法,编译器可以直接将a->i替换为常量值1。
内容的提问来源于stack exchange,提问作者Ayrosa
相关产品推荐
相关产品推荐

