静态数据成员的地址

Dai*_*ner 0 c++ static-members

为什么当数据成员在类内初始化且没有类外定义时,C++ 不允许获取静态数据成员的地址?在这种情况下,静态成员的存储空间是如何分配的?

下面的最小程序演示了这个问题。

#include <iostream>

class Test {
public:
    static const int a = 99;   // how is the storage allocated for Test::a??
};

// const int Test::a;

int main() {
    std::cout << Test::a << '\n';  // OK, print 99
    const int* ptr = &Test::a;     // Linker error, undefined reference to Test::a
}
Run Code Online (Sandbox Code Playgroud)

如果我取消注释该行const int Test::a,那么程序就可以正常工作。

Nel*_*eal 5

这一行是一个声明:

static const int a = 99;
Run Code Online (Sandbox Code Playgroud)

这不是一个定义。对于要分配的存储,您需要一个定义。这就是您的注释行发挥作用的地方。

Test::a即使它没有定义,您也可以使用,因为它被视为编译时常量。一般来说,static const T变量(其中T是普通类型)一旦被常量初始化就必须可以在常量表达式中使用。

请注意,您可以同时获得两种行为(编译时常量和带有地址的变量):

class Test {
public:
    static const int a = 99;
};

const int Test::a;

template<int i>
struct Templated {};

int main() {
    const int* ptr = &Test::a;
    Templated<Test::a> a;
}
Run Code Online (Sandbox Code Playgroud)

演示

并说明常量初始化点:

class Test {
public:
    static const int a;
};

template<int i>
struct Templated {};

// does not compile because Test::a is *not yet* usable in a constant expression
Templated<Test::a> global;

const int Test::a = 99;

int main() {
    const int* ptr = &Test::a;
    Templated<Test::a> a;
}
Run Code Online (Sandbox Code Playgroud)

演示

  • 您还可以将成员切换为“static constexpr int a = 99;”,现在不需要任何外线定义。 (2认同)