【问题标题】:How to access the address of a static const member of a class?如何访问类的静态 const 成员的地址?
【发布时间】:2013-08-07 15:09:38
【问题描述】:

这段代码没有编译,错误信息是“undefined reference to `A::a'”:

代码 1:

#include <iostream>
using namespace std;

class A
{
public:
    static const int a=0;
};

int main()
{
    cout<<&A::a<<endl;
    return 0;
}

但对于非常量静态成员,它会编译:

代码 2:

#include <iostream>
using namespace std;

class A
{
public:
    static int a;
};
int A::a=0;

int main()
{
    cout<<&A::a<<endl;
    return 0;
}

有没有办法访问一个类的静态 const 成员的地址?如果有,怎么做?为什么代码 1 不能编译?

【问题讨论】:

  • 令人讨厌的是,它似乎在 VS2012 上链接正常
  • @doctorlove 我的编译器是 Linux 上的 g++。
  • 那时比我更懂事。我想知道为什么它在 VS 上可以正常链接。

标签: c++


【解决方案1】:

const int A::a;

在源文件中,否则编译器不会为 a 生成地址。注意这里的值不重复。

【讨论】:

  • 你用的是什么编译器?
  • 对于整数,您可以将值放在头文件(/类定义)中。这允许编译器直接使用该值在其他源文件中进行优化和数组大小。但实际上分配地址的是源文件中的行。这是因为整个项目的内存中只有一个静态类的实例,所以它只能出现在一个翻译单元中。没有它,该值实际上永远不会作为内存中的真实对象存在。该值只是被编译器“复制并粘贴”到它被调用的地方,然后被遗忘。
【解决方案2】:

此代码无法编译

代码没有链接,它可以编译。 static const 成员如果要使用它的地址,则需要一个定义,所以只需添加一个类似于第二个代码sn-p的定义:

const int A::a;

A::a的地址意味着A::aodr-used,来自C++11标准(草案n3337)的9.4.2静态数据成员节,子句3:

如果一个非 volatile const 静态数据成员是整数或枚举类型,它在类中的声明 定义可以指定一个大括号或等式初始化器,其中每个初始化器子句都是一个赋值表达式 是一个常数表达式 (5.19)。文字类型的静态数据成员可以在 带有 constexpr 说明符的类定义;如果是这样,它的声明应指定一个大括号或相等初始化器 其中作为赋值表达式的每个初始化子句都是常量表达式。 [注:在这两个 在这些情况下,成员可能出现在常量表达式中。 —尾注] 成员仍应定义 如果在程序中使用了 odr-used (3.2) 并且命名空间范围定义不应在命名空间范围内 包含一个初始化程序。

【讨论】:

    【解决方案3】:

    既然你想取地址,你仍然需要定义静态成员,就像你对你所说的非常量版本所做的那样

    int A::a;
    

    const 版本你还需要

    const int A::a;
    

    请参阅here 以获得良好的讨论 - 标题引述 “编译时常量没有地址。”

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-04-18
      • 1970-01-01
      • 1970-01-01
      • 2018-10-05
      • 2012-12-13
      • 1970-01-01
      相关资源
      最近更新 更多