为什么S :: x没有使用?

时间:2017-12-23 11:18:40

标签: c++ language-lawyer c++17

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的名称显示为可能评估的表达式ex的变量exx odr-used 除非

     
      
  • ...
  •   
  • 如果ex是对象,则 e是表达式e 的潜在结果集的元素,其中      
        
    • 左值到右值转换(7.1)适用于e
    •   
    • &S::x是一个废弃值表达式(第8条)
    •   
  •   

问题在于丢弃值表达式S::x没有可能的结果(这意味着&S::x不是e的潜在结果),正如您在6.2中看到的那样,第2段[basic.def.odr]:

  

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

     
      
  • 如果e是id-expression(8.1.4),则该集仅包含e
  •   
  • 如果S::x是带有数组操作数的下标操作(8.2.1),则该集合包含该操作数的潜在结果。
  •   
  • ...
  •   
  • 否则,该集为空。
  •   

然后,你怎么解释$db->RecordCount()没有使用过多的东西?

3 个答案:

答案 0 :(得分:4)

它确实很用。您的分析是正确的(我已修复了示例a while ago)。

答案 1 :(得分:0)

是的,在示例中,&S::x odr-uses S::x

  

[basic.def.odr]/4

     

除非应用左值到右值的转换,否则x的名称显示为可能评估的表达式ex的变量ex odr-used x产生一个常量表达式,它不会调用任何非平凡的函数,如果x是一个对象,ex是一个表达式e的潜在结果集的元素,其中lvalue-to-rvalue转换应用于e,或者e是丢弃值表达式。

对象的地址永远不是常量表达式。这就是为什么S::x&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的评估;

答案 2 :(得分:-3)

声明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”。

因此,我的结论是:在不使用地址的情况下取得地址,根本不计算