为什么s :: x不使用ODR
Why is S::x not odr-used?
从cppreference中考虑此示例:
struct S { static const int x = 1; };
void f() { &S::x; } // discarded-value expression does not odr-use S::x
我同意 &S::x
是 dasved-value表达式,因为标准说(9.2,段落1 [stmt.expr] N4700)
表达式语句具有形式
expression-statement: expression_opt ;
表达式是一个丢弃的值表达式(第8条)...
但是,对于S::x
而言,这足以不被 odr使用?6.2,第3段[basic.def.odr]状态
x
的变量CC_3,其名称以潜在评估的表达式ex
是 odr used ,除非
- ...
- 如果
x
是一个对象,ex
是表达式e
的潜在结果集的元素
- 将LVALUE到RVALUE转换(7.1)应用于
e
或e
是一个丢弃的值表达式(第8条)。
问题是丢弃的值表达式&S::x
没有潜在的结果(这意味着S::x
不是&S::x
的潜在结果),正如您可以从6.2,第2段[Basic.Def.odr]段中看到的那样:blockquote>
...表达式e
的潜在结果集定义如下:
- 如果
e
是ID-表达(8.1.4),则该集合仅包含e
。 - 如果
e
是带有数组操作数的订阅操作(8.2.1),则该集合包含该操作数的潜在结果。 - ...
- 否则,该集合为空。
那么,您如何解释S::x
没有使用ODR?
它确实被用了。您的分析是正确的(我在不久前修复了该示例)。
是的,在示例中, &S::x
odr-uses S::x
。
[basic.def.odr]/4
一个可变的
x
,其名称显示为潜在评估的表达式ex
是 odr-odr-使用,除非将lvalue-to-rvalue转换x
应用于 CC_25>不调用任何非平凡的功能,如果x是对象,则EX是表达式E的潜在结果集的元素,其中lvalue-to-rvalue转换应用于E,或者E是丢弃的价值表达式。
对象的地址绝不是恒定的表达式。这就是为什么S::x
在&S::x
中使用ODR。
证明最后断言是合理的:
[expr.const]/6
常数表达式是glvalue核心常数表达式,它是指一个实体,该实体是恒定表达式的允许结果(如下所示),或者是一个值得满足以下约束[...]的prvalue core常数表达式表达式表达式。
和
[expr.const]/2.7
2)表达式
e
是核心常数表达式,除非遵循摘要机器的规则评估e
,,将评估以下表达式之一:
[...]
2.7)除非将其应用于
(以下几点都不适用:)
2.7.1)积分或枚举类型的非易失性glvalue,它指的是具有前面初始化的完整的非挥发性const对象,并以恒定表达式初始化,或者
的评估中开始
2.7.2) 一个非易失性的glvalue,是指字符串字面的子对象,或者
2.7.3) 一种非易失性的glvalue,它是指用constexpr定义的非易失性对象,或者指的是这种对象的不可弹性子对象,或者
2.7.4) 字面类型的非易失性glvalue是指非易失性对象,其寿命开始在e
;
在声明const int
时,除非您使用其地址,否则它可以完全由编译器丢弃。服用地址还不够。
丢弃并不意味着该值未评估,它是,而是意味着没有包含const值的内存地址,编译器只需用其值替换const变量,因为它只是一个宏。
此外,在将指针拿到指针并从指针中夺回值时,不会给编译器留下太大的印象,它只是忽略并使用该值。
以下代码显示,可以编译并运行此代码(我通过几个编译器对其进行了测试,我仍然不确定它是否成功地编译了...),尽管没有声明S::x
:
#include <iostream>
using namespace std;
struct S
{
static const int x=0;
};
//const int S::x; //discarded
int main()
{
const int *px = &S::x; //taking the address
cout<< *px <<endl; //print the value - OK
return 0;
}
但是,如果我尝试使用地址本身(而不是值),则如下:
cout<< px <<endl; //print the address - Will be failed
该链接将使DOU失败至:"未定义的S::x
"。
因此,我的结论是:在不使用的情况下进行地址,根本不计数。
- 为什么"do while"循环不断退出,即使条件计算结果为 false?
- 为什么在全局范围内使用"extern int a"似乎不行?
- 为什么在popback()操作之后,它仍然打印完整的矢量
- 为什么随机数生成器不在void函数中随机化数字,而在main函数中随机化
- 为什么两个不同的未命名名称空间可以共存于一个cpp文件中
- 为什么会发生堆损坏
- 为什么使用 "this" 指针调用派生成员函数?
- C++我的数学有什么问题,为什么我的代码不能正确循环
- 为什么比较运算符如此快速
- 为什么显式模板实例化不会破坏 ODR?
- 为什么编译器不在同一翻译单元中警告 ODR 违规
- 为什么调用成员函数不调用该对象的 ODR-USE?
- 为什么结构声明在C++中违反了 ODR
- 为什么“静态”功能在不同的tu中不会破坏ODR
- 为什么在标题上的结构中声明的模板不违反 ODR 并且专用化会违反 ODR
- 为什么s :: x不使用ODR
- 根据 [basic.def.odr]/2,'A::a[0]' 的潜在结果集为空.为什么它是空的?
- 为什么静态成员的类内初始化会违反 ODR
- 在这种情况下,为什么一个定义规则(ODR)不被g++所接受?.
- 为什么不通过获取内联定义的静态常量整数成员变量的地址来违反 ODR?