Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/143.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 为什么不使用odr?_C++_Language Lawyer_C++17 - Fatal编程技术网

C++ 为什么不使用odr?

C++ 为什么不使用odr?,c++,language-lawyer,c++17,C++,Language Lawyer,C++17,从以下方面考虑此示例: 我同意&S::x是一个废弃的值表达式,因为标准中说(9.2,第1段[stmt.expr]) 表达式语句具有以下形式: expression-statement: expression_opt ; 表达式是一个废弃的值表达式(第8条) 然而,对于不使用odr的S::x来说,这足够了吗?6.2第3段[基本定义odr]规定 变量x的名称显示为可能计算的表达式ex是ex使用的odr,除非 如果x是一个对象,ex是表达式e的潜在结果集的一个元素,其中 左值到右值的转

从以下方面考虑此示例:

我同意
&S::x
是一个废弃的值表达式,因为标准中说(9.2,第1段[stmt.expr])

表达式语句具有以下形式:

expression-statement:
    expression_opt ;
表达式是一个废弃的值表达式(第8条)

然而,对于不使用odr的
S::x
来说,这足够了吗?6.2第3段[基本定义odr]规定

变量
x
的名称显示为可能计算的表达式
ex
ex
使用的odr,除非

  • 如果
    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
未使用odr?

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

变量
x
的名称显示为可能计算的表达式
ex
ex
使用的odr,除非将左值到右值的转换应用于
x
会产生一个常量表达式,该表达式不调用任何非平凡函数,并且如果x是一个对象,ex是表达式e的潜在结果集的一个元素,其中左值到右值的转换应用于e,或者e是丢弃的值表达式

对象的地址从来不是一个常量表达式。这就是为什么在
&s::x
中使用odr的原因

为了证明最后的断言是正确的:

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

2) 表达式
e
是一个核心常量表达式,除非遵循抽象机器规则
e
的求值将求值以下表达式之一:
[…]
2.7)左值到右值的转换,除非适用于

(以下各点均不适用:)

2.7.1)整型或枚举型的非易失性glvalue,指的是一个完整的非易失性常量对象,具有前面的初始化、用常量表达式初始化或
2.7.2) 引用字符串文字的子对象的非易失性glvalue,或
2.7.3) 一种非易失性glvalue,它引用用constexpr定义的非易失性对象,或引用此类对象的不可变子对象,或
2.7.4) 一种文本类型的非易失性glvalue值,指的是一个非易失性对象,其生存期开始于
e
的计算范围内


声明
const int
时,编译器可能会完全丢弃它,除非使用它的地址获取地址不够

丢弃并不意味着不计算该值,而是意味着没有包含常量值的内存地址,编译器只是用它的值替换常量变量,因为它只是一个宏

此外,当获取指向它的指针并从指针中获取值时,不会给编译器留下太多印象,它只是忽略它并使用该值

下面的代码显示了这一点,尽管没有声明
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;
}
#包括
使用名称空间std;
结构
{
静态常数int x=0;
};
//常量int S::x//丢弃的
int main()
{
const int*px=&S::x;//获取地址

cout确实使用了odr。您的分析是正确的(我修复了该示例)。

标准措辞的另一个问题是,
S::x
不是一个名称。它是一个限定id。但显然是“一个变量x,其名称…”也应该适用于
x
作为一个合格的id。是的,这是我们这边的一个bug。修复了@M.M类似的东西?@T.C.让丢弃的值表达式
&s::x
odr使用
x
?@xskxzr获取某个东西的地址通常要求该东西存在。雕刻出来的好处是什么这种情况下的例外情况是:问题是被标记的,这意味着OP希望得到ISO C++标准的引用支持。它编译是不相关的(实际上很多ODR违规编译得很好)。。我不打算写一个答案只是为了确认我在评论中写的内容,但出于某种原因,这个问题吸引了很多错误的答案:|我很感激。谢谢!
&S::x
不是左值(因此不能进行左值到右值的转换),而
&
不会导致
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