6

我的印象是,无论是在命名空间范围内声明还是在类/结构/联合内声明,C++ 都将相同的特殊规则应用于static const整数类型。

现在我在想我已经被不兼容的编译器教坏了。

static const int A = 1;

struct s
{
    static const int A = 1;
};

除了范围上的明显差异之外,如何As::A不同?

  • ...什么时候它们的用法将被它们的字面值替换?
  • ...我什么时候可以拿到它的地址?
  • ...当我需要单独定义它们时?

我特别好奇 C++ 03。

4

2 回答 2

6

关键字static在类范围和命名空间范围内的含义不同。事实上,它在命名空间范围内的使用已被弃用。

在类范围内声明变量时,static意味着该变量只有一个实例,具有静态存储持续时间和生命周期。类中的声明不是定义;如果使用了变量则必须在一个(并且只有一个)翻译单元中定义它;如果未定义,则您的行为未定义。(在实践中,根据使用情况,要么一切正常,要么链接器出错。)请注意,如果声明是针对const整型的,并且包含初始化,那么 如果它是在需要常量整数表达式的上下文中使用(如 C 样式数组的维度)。最简单和最可靠的事情就是在某个地方定义它。

在命名空间范围内声明变量时,static意味着该名称具有内部链接,而不是外部链接;不管有没有static,声明都是一个定义(所以程序中应该没有其他定义)。在 C++03 中,这种用法已被弃用;改用未命名的命名空间。还要注意,如果变量本身是const(顶级 const),则默认情况下它具有内部链接,因此static没有任何效果。(如果您需要const具有外部链接的变量,请将其设为类成员,或显式定义它extern,使用初始化程序使其成为定义,而不仅仅是声明。)

于 2012-12-18T15:54:30.020 回答
0

怎么做As::A区别?

最大的不同是声明ofA也是定义,而声明ofs::A不是。我不确定您所说的“特殊规则”是什么意思,但static在每种情况下都有不同的含义。

在命名空间范围内,它为其提供内部链接,以便对象在当前翻译单元之外不可见。请注意,static这里是多余的,因为默认情况下命名空间范围内的常量变量具有内部链接。

在类范围内,这意味着有一个独立于类的任何实例的对象。

什么时候它们的用法将被它们的字面值替换?

由于两者都是在声明中带有初始化器的整数常量,因此两者都可以在常量表达式中使用,并且编译器能够用编译时常量替换它们的值。

也许更合适的问题是,什么时候需要定义?

在 C++11 中,如果变量是odr-used ,则它是必需的- 粗略地说,如果您执行任何需要变量地址而不是其值的事情。

在 C++03 中,我认为如果完全使用该变量是必需的,尽管不需要诊断,而且如果您只使用它的值,许多编译器也不会抱怨。不过我可能是错的;旧规则相当复杂,我很高兴现在能够忘记它们。

我什么时候可以取到它的地址?

这要求变量在 C++03 和 C++11 中都有定义。该定义为变量分配存储空间,使其具有地址。

当我需要单独定义它们时?

命名空间范围内的变量声明也是一个定义,除非您声明它extern;所以你的第一个变量不需要单独的定义。

类范围的变量声明不是定义;所以你的第二个变量确实需要在 C++03 和 C++11 中单独定义,如果它是odr-used

于 2012-12-18T17:05:03.620 回答