获取静态成员C+的地址+;常见问题 < C++ FAQ试图传达什么?

获取静态成员C+的地址+;常见问题 < C++ FAQ试图传达什么?,c++,C++,如果(且仅当)静态成员具有类外定义,则可以获取其地址: 但是,您可以使用-O2进行编译。编译器可以优化掉常量int*p1=&AE::c6赋值(因为它没有效果),因此在最终代码中不需要地址AE::c6,这就是它编译的原因 它给出了一个链接器错误,没有进行优化 如果您开始使用p1(例如std::cout常见问题解答中的注释具有误导性;AE::c6和 AE::c7是左值。如果没有对AE::c7的定义, 相关代码违反了“一个定义”规则: 表达式可能会被计算,除非它是 未赋值的操作数或其子表达式。变量 其

如果(且仅当)静态成员具有类外定义,则可以获取其地址:


但是,您可以使用
-O2

进行编译。编译器可以优化掉
常量int*p1=&AE::c6赋值(因为它没有效果),因此在最终代码中不需要地址
AE::c6
,这就是它编译的原因

它给出了一个链接器错误,没有进行优化


如果您开始使用
p1
(例如
std::cout常见问题解答中的注释具有误导性;
AE::c6
AE::c7
是左值。如果没有对
AE::c7
的定义, 相关代码违反了“一个定义”规则:

表达式可能会被计算,除非它是 未赋值的操作数或其子表达式。变量 其名称显示为可能计算的表达式是 除非是满足要求的对象,否则使用odr 用于出现在常量表达式中,并将左值转换为右值 立即应用转换。[…]

[……]

每个程序应包含每个程序的一个定义 odr在其中使用的非内联函数或变量 编程;无需诊断

实际上,链接器通常会在以下情况下生成错误: 编译器实际上需要对象的地址 在这种情况下,如果以后不使用
p2
,则编译器将不需要 地址,因为优化将删除
p1
的定义。 发生这种情况的更常见的情况是 以下:

std::vector<int> v;
v.push_back( AE::c6 );
std::vector v;
v、 推回(AE::c6);
由于
std::vector::push_back
接受一个引用,因此没有 立即将左值转换为右值,定义为 必需。实际上,
std::vector::push_back
是一个模板 函数(通常是内联函数),因此编译器可以查看其 实现,并将值向下传播到函数中 到左值到右值转换实际发生的位置 发生,代码将编译并工作。但它仍然是
形式上未定义的行为。

如果分别编译
类AE
f()
,然后链接对象,会发生什么情况?@juanchopanza它使用
-O2
f()编译
本质上是一个nop。然而,它给出了一个链接器错误,
-O0
,就像原始程序对
-O0
@Csq所做的那样。是的,我看到并投票了你的答案。或者,
std::cout这里有一个相关链接,最初在我对删除答案的评论中:这可能也有关联:好的,我会说同样的话这里也是(正如我在一个已删除的答案中所说的),FAQ IMO中的注释
//error:c6不是左值
具有误导性,乍一看这似乎是一个语法错误。链接器错误是显而易见的,但优化后我却意外地不知道
std::vector<int> v;
v.push_back( AE::c6 );