引用静态数据成员

时间:2018-06-28 14:45:27

标签: c++ reference static

我正在阅读有关将引用绑定到静态数据成员或获取其地址的信息,前提是(且仅当)引用具有类外定义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)。

所以我有2个问题:

  1. 这里的一元+角色是什么?
  2. 为什么编译器忽略了错误const int* p1 = &AE::c6;,这不是我所期望的?

1 个答案:

答案 0 :(得分:3)

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

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

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