【问题标题】:Why we have to define a const static member that is initialized within a class为什么我们必须定义一个在类中初始化的 const 静态成员
【发布时间】:2012-04-04 20:59:16
【问题描述】:

众所周知,可以在类结构内部初始化整型const静态成员。这在初始化后的类结构中使用常量时很有用。例如,它可以用作int的大小大批。 看下面的代码:

class MyClass{
static const int num = 100;
int elems[num];
...
};

但是我们还是要在类定义之外定义成员num

const int MyClass::num;

我不知道为什么我们必须这样做。 有人能告诉我为什么吗? 非常感谢。

另外,我写了如下代码:

#include <iostream>
using namespace std;

class MyClass{
public:
MyClass()
{
    cout << "instruct class MyClass!" << endl;
}
static const int num = 100;
int elems[num];
};

//const int MyClass::num;

int main()
{
MyClass a;
const int *b = &(a.num);
cout << "&(a.num): " << &(a.num) << endl;
cout << "a.num: " << a.num << endl;
cout << "*b: " << *b << endl;
}

它在 Visual Studio 2008 上运行良好:

但是我已经删除了定义类外成员num的代码。

我很困惑。有人可以帮我解释一下吗?

【问题讨论】:

    标签: c++ object initialization static-members


    【解决方案1】:

    类中的初始化主要用于获取常量表达式。为此,只有价值很重要。一旦获取对象的地址或将其绑定到引用,编译器也需要对象的位置。这实际上就是定义所提供的。

    【讨论】:

    • 但是编译器可以像处理模板的静态成员或内联函数一样处理它,这两者在多个文件中都有定义,但仍然需要一个地址。
    • @JamesKanze:对于模板的静态成员,您仍然需要一个实际上非常烦人的定义,因为隐式实例化对此不起作用。我猜它可以表现得像内联函数中的静态变量。我的理解是,这些通过创建具有弱符号的函数来工作,这些符号在链接时被丢弃。然而,该语言目前需要定义,尽管编译器可能不会坚持存在。
    • 我知道。我只是说从技术上讲,不需要定义不是问题,因为在其他情况下也需要支持不需要定义的编译器技术。
    【解决方案2】:

    只有当您的代码采用其地址时,您才需要在 cpp 文件中的类外部定义静态常量 num。这称为类外定义
    如果您的代码不采用num 的地址,那么类内初始化 就可以正常工作。

    理由:

    比亚恩states

    “C++ 要求每个对象都有一个唯一的定义。如果 C++ 允许在类内定义需要作为对象存储在内存中的实体,则该规则将被打破。”

    请注意,只有static const 整数可以被视为编译时常量。编译器知道整数值不会随时改变,因此它可以应用自己的魔法并应用优化,编译器只是内联此类成员,即它们不再存储在内存中,因为不需要存储在内存中,它为这些变量提供了 Bjarne 提到的上述规则的例外。

    即使static const 整数值可以进行类内初始化,也不允许获取此类变量的地址。当(且仅当)静态成员具有类外定义时,可以获取静态成员的地址,因为编译器需要将它们放在内存中。

    【讨论】:

    • 终于明白了。非常感谢!非常感谢您的回复!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-05-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多