繁体   English   中英

为什么不使用S :: x?

[英]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丢弃值表达式 ,由于标准说(9.2,第1段[stmt.expr]从N4700

表达式语句具有以下形式

 expression-statement: expression_opt ; 

该表达式是一个废弃值表达式(第8条)...

但是,足以让S::x不被使用吗? 6.2第3段[basic.def.odr]指出

变量x ,其名称显示为潜在评估表达exODR-使用 ex ,除非

  • ...
  • 如果x是对象,则ex是表达式e的一组潜在结果的元素 ,其中
    • 左值到右值转换(7.1)应用于e ,或者
    • e是一个舍弃值表达式(第8条)

问题是,废弃值表达式&S::x没有潜在结果(这意味着S::x不是&S::x的潜在结果),如您从6.2第2段中所见[basic.def .odr]:

...表达式e的潜在结果集定义如下:

  • 如果e是id表达式(8.1.4),则该集合仅包含e
  • 如果e是具有数组操作数的下标操作(8.2.1),则该集合包含该操作数的潜在结果。
  • ...
  • 否则,集合为空。

然后,您如何解释S::x未被使用?

它确实是很少使用的。 你的分析是正确的(我固定的例如前一阵子 )。

是的,在示例中, &S::x odr使用S::x

[basic.def.odr]/4

变量x ,其名称显示为潜在评估表达exODR-使用 ex ,除非施加左值到右值转换到x产生一个常量表达式不调用任何非平凡的功能,并且如果x是一个对象,ex是表达式e的一组潜在结果的元素,其中将左值到右值转换应用于e或e是舍弃值表达式。

对象的地址绝不是常量表达式。 这就是为什么S::x就是ODR-应用于&S::x

为了证明最后一个断言的合理性:

[expr.const]/6

常量表达式可以是glvalue核心常量表达式,指的是作为常量表达式允许的结果的实体(如下定义),或者是prvalue核心常量表达式,其值满足以下约束[...]

[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

链接将失败,原因是:“对S::x未定义引用”。

因此,我的结论是: 不使用地址就不算什么

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM