【问题标题】:Taking address of a static member C++ FAQ获取静态成员的地址 C++ FAQ
【发布时间】:2014-06-19 17:41:13
【问题描述】:

this C++ FAQ 试图传达什么?

当(且仅当)静态成员具有类外定义时,您可以获取静态成员的地址:

class AE {
    // ...
public:
    static const int c6 = 7;
    static const int c7 = 31;
};

const int AE::c7;   // definition

int f()
{
    const int* p1 = &AE::c6;    // error: c6 not an lvalue
    const int* p2 = &AE::c7;    // ok
    // ...
}

不过这个compiles !

【问题讨论】:

  • 如果分别编译class AEf()然后链接对象会怎样?
  • @juanchopanza 它与-O2f() 编译本质上是一个nop。但是,它使用-O0 会导致链接器错误,就像原始程序使用-O0 一样。
  • @Csq 是的,我看到并赞成您的回答。或者,std::cout << p1 << std::endl; 将在操作中进行。
  • 这是一个相关链接,最初在我对已删除答案的评论中:en.wikipedia.org/wiki/…
  • 这也可能是相关的:stackoverflow.com/questions/14547370/…

标签: c++


【解决方案1】:

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

它在没有优化的情况下给出了一个链接器错误。

如果您开始使用p1(例如std::cout << p1 << p2 << std::endl;Link,也会出现链接器错误

【讨论】:

  • 好的,我也会在这里说同样的话(正如我所说的是在一个已删除的答案中),常见问题 IMO 中的评论 // error: c6 not an lvalue 具有误导性,这似乎是一个语法错误乍一看。链接器错误很明显,但优化后我竟然不知道
【解决方案2】:

FAQ 中的评论非常具有误导性; AE::c6AE::c7 是左值。如果没有AE::c7的定义, 有问题的代码违反了单一定义规则:

一个表达式可能会被计算,除非它是 未计算的操作数或其子表达式。一个变量 其名称显示为可能求值的表达式是 odr-used 除非它是满足要求的对象 用于出现在常量表达式和左值到右值 立即应用转换。 [...]

[...]

每个程序都应该包含一个定义 用于 odr 的非内联函数或变量 程序;无需诊断。

在实践中,链接器一般会产生错误if 编译器实际上需要对象的地址。在你的 情况下,如果以后不使用p2,那么编译器就不需要 地址,因为优化将删除p1 的定义。 发生这种情况的更常见的情况是 以下:

std::vector<int> v;
v.push_back( AE::c6 );

由于std::vector&lt;&gt;::push_back 有引用,所以没有 立即左值到右值转换,定义是 必需的。在实践中,std::vector&lt;&gt;::push_back 是一个模板 函数(通常是内联的),所以编译器可以看到它的 实现,并将值向下传播到函数中 到实际进行左值到右值转换的地方 发生,代码将编译并工作。但它仍然 正式未定义的行为。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-04-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多