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
的变量ex
由x
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()
没有使用过多的东西?
答案 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
”。
因此,我的结论是:在不使用地址的情况下取得地址,根本不计算。