我正在阅读有关将引用绑定(bind)到静态数据成员或获取其地址的信息,如果(且仅当)它具有类外定义
(https://isocpp.org/wiki/faq/classes-and-objects#in-class-constant)。

当我尝试测试该示例时(请参见下文),我注意到它可以在Visual Studio 2017上运行(没有预期的错误)。

我尝试使用在线编译器,但只有一个错误(没有两个像预期的那样)。

#include <iostream>
using namespace std;

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

const int AE::c7; // definition
void byref(const int& a);


int main(int argc, char* argv[])
{
    byref(AE::c6); // error: c6 not an lvalue
    byref(AE::c7); // ok
    const int* p1 = &AE::c6; // error: c6 not an lvalue
    const int* p2 = &AE::c7; // ok

    std::cout << "p1 " << *p1 << "\n";
    std::cout << "p2 " << *p2 << "\n";
    return 0;
}

void byref(const int & a)
{
    std::cout << a << "\n";
}

暂时忽略Microsoft编译器...

编译该程序时,我得到了undefined reference to AE::c6,通过在堆栈上找到一些技巧,将其更改为byref(+AE::c6);即可解决该问题。

但是对于注释所示的另一行const int* p1 = &AE::c6;,它将生成不是这种情况的错误(它会编译并运行OK)。

所以我有两个问题:
  • 这里的一元+角色是什么?
  • 为什么编译器会忽略错误const int* p1 = &AE::c6;,这不是我所期望的?
  • 最佳答案

    对于第一个问题,在常量名称前面添加+会将值从常量更改为表达式。表达式的结果存储在一个未命名的临时变量中,并将对该临时变量的引用传递给byref。如果没有+,则直接引用该常数,这要求该常数在程序中的某个位置具有定义。

    对于第二个问题,编译器将不会在编译期间发出诊断信息,因为o​​jit_code的一个定义可能存在于另一个源文件中。找不到定义时,链接器将提供错误。

    [class.static.data]中的语言标准说:“应该在程序中完全使用一个静态数据成员的定义(6.2);没有
    诊断是必需的。”因此,没有定义或不止一个定义是一种违规,但不需要报告。在前一种情况下,编译器/链接器可以创建要使用的定义,而在后一种情况下,链接器将只选择可用的定义之一。

    08-04 09:35