为什么我不能在类中初始化非常量静态成员或静态数组? [英] Why can't I initialize non-const static member or static array in class?

查看:423
本文介绍了为什么我不能在类中初始化非常量静态成员或静态数组?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为什么不能在类中初始化非常量 static 成员或 static 数组?

Why can't I initialize non-const static member or static array in a class?

class A
{
    static const int a = 3;
    static int b = 3;
    static const int c[2] = { 1, 2 };
    static int d[2] = { 1, 2 };
};

int main()
{
    A a;

    return 0;
}

编译器会发出以下错误:

the compiler issues following errors:

g++ main.cpp
main.cpp:4:17: error: ISO C++ forbids in-class initialization of non-const static member ‘b’
main.cpp:5:26: error: a brace-enclosed initializer is not allowed here before ‘{’ token
main.cpp:5:33: error: invalid in-class initialization of static data member of non-integral type ‘const int [2]’
main.cpp:6:20: error: a brace-enclosed initializer is not allowed here before ‘{’ token
main.cpp:6:27: error: invalid in-class initialization of static data member of non-integral type ‘int [2]’

我有两个问题:


  1. 为什么我不能初始化 static 类中的数据成员?

  2. 为什么我不能初始化类中的 static 数组,即使 const 数组?

  1. Why can't I initialize static data members in class?
  2. Why can't I initialize static arrays in class, even the const array?


推荐答案

为什么我不能进入是否对类中的 static 数据成员进行初始化?



C ++标准仅允许在内部初始化静态常量积分或枚举类型班级。这就是允许 a 初始化而其他人则不允许初始化的原因。

Why I can't initialize static data members in class?

The C++ standard allows only static constant integral or enumeration types to be initialized inside the class. This is the reason a is allowed to be initialized while others are not.

参考:

C ++ 03 9.4.2静态数据成员

§4

Reference:
C++03 9.4.2 Static data members
§4


如果静态数据成员为const整型或const枚举类型,则其在类定义中的声明可以指定一个常量初始化器,该初始化器应为整数常量表达式(5.19)。在这种情况下,成员可以出现在整数常量表达式中。如果在程序中使用了该成员,则该成员仍应在命名空间范围内定义,并且该命名空间范围定义不应包含初始化程序。

If a static data member is of const integral or const enumeration type, its declaration in the class definition can specify a constant-initializer which shall be an integral constant expression (5.19). In that case, the member can appear in integral constant expressions. The member shall still be defined in a namespace scope if it is used in the program and the namespace scope definition shall not contain an initializer.

什么是整数类型?

C ++ 03 3.9.1基本类型

§7

C++03 3.9.1 Fundamental types
§7


类型bool,char,wchar_t以及有符号和无符号整数类型统称为整数类型。43)的同义词整数类型是整数类型。

Types bool, char, wchar_t, and the signed and unsigned integer types are collectively called integral types.43) A synonym for integral type is integer type.

脚注:


43)因此,枚举(7.2)不是整数;但是,可以将枚举提升为int,unsigned int,long或unsigned long(如4.5中所述)。

43) Therefore, enumerations (7.2) are not integral; however, enumerations can be promoted to int, unsigned int, long, or unsigned long, as specified in 4.5.



解决方法:



您可以使用枚举把戏初始化类定义中的数组。

Workaround:

You could use the enum trick to initialize an array inside your class definition.

class A 
{
    static const int a = 3;
    enum { arrsize = 2 };

    static const int c[arrsize] = { 1, 2 };

};



为什么标准不允许这样做?



Bjarne在 此处 进行了恰当的解释:

Why does the Standard does not allow this?

Bjarne explains this aptly here:


一个类通常在头文件中声明,并且头文件通常包含在许多翻译单元中。但是,为避免复杂的链接器规则,C ++要求每个对象都有唯一的定义。如果C ++允许在类中定义需要作为对象存储在内存中的实体,则该规则将被打破。

A class is typically declared in a header file and a header file is typically included into many translation units. However, to avoid complicated linker rules, C++ requires that every object has a unique definition. That rule would be broken if C++ allowed in-class definition of entities that needed to be stored in memory as objects.



为什么只有静态常量整数类型&



答案被隐藏在Bjarne的报价中,请仔细阅读,

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

Why are only static const integral types & enums allowed In-class Initialization?

The answer is hidden in Bjarne's quote read it closely,
"C++ requires that every object has a unique definition. That rule would be broken if C++ allowed in-class definition of entities that needed to be stored in memory as objects."

只能将 static const 整数视为编译时间常数。编译器知道整数值不会随时更改,因此它可以运用自己的魔力并进行优化,编译器只是内联此类成员,即它们不再存储在内存中,因为不再需要存储在内存中,它为此类变量提供了Bjarne提到的规则的例外。

Note that only static const integers can be treated as compile time constants. The compiler knows that the integer value will not change anytime and hence it can apply its own magic and apply optimizations, the compiler simply inlines such class members i.e, they are not stored in memory anymore, As the need of being stored in memory is removed, it gives such variables the exception to rule mentioned by Bjarne.

在这里值得注意的是,即使 static const 整数值可以具有In-Class初始化,也可以使用地址不允许使用此类变量。如果(且仅当)静态成员的定义超出类,则可以使用该静态成员的地址。这进一步验证了上面的推理。

It is noteworthy to note here that even if static const integral values can have In-Class Initialization, taking address of such variables is not allowed. One can take the address of a static member if (and only if) it has an out-of-class definition.This further validates the reasoning above.

之所以允许使用枚举,是因为可以在需要整数的地方使用枚举类型的值。请参见上文引文

enums are allowed this because values of an enumerated type can be used where ints are expected.see citation above

C ++ 11放松了限制到一定程度。

C++11 relaxes the restriction to certain extent.

C ++ 11 9.4.2静态数据成员

§3

C++11 9.4.2 Static data members
§3


如果静态数据成员为const文字类型,则其在类定义中的声明可以指定 brace-or-equal-initializer ,其中每个 initializer-clause 是一个常量表达式,它是一个 assignment-expression 。可以使用 constexpr说明符在类定义中声明文字类型的静态数据成员; 如果这样,则其声明应指定 brace-or-equal-initializer ,其中每个 assignment-expression 初始化器子句都是一个常数表达式。 [注意:在这两种情况下,成员都可能出现在常量表达式中。 — —注释—如果在程序中使用了该成员,则该成员仍应在命名空间范围内定义,并且该命名空间范围定义不应包含初始化程序。

If a static data member is of const literal type, its declaration in the class definition can specify a brace-or-equal-initializer in which every initializer-clause that is an assignment-expression is a constant expression. A static data member of literal type can be declared in the class definition with the constexpr specifier; if so, its declaration shall specify a brace-or-equal-initializer in which every initializer-clause that is an assignment-expression is a constant expression. [ Note: In both these cases, the member may appear in constant expressions. —end note ] The member shall still be defined in a namespace scope if it is used in the program and the namespace scope definition shall not contain an initializer.

此外,C ++ 11 允许(第12.6.2.8节)一个非静态数据成员在其声明的位置(在其类中)进行初始化。这将意味着简单的用户语义。

Also, C++11 will allow(§12.6.2.8) a non-static data member to be initialized where it is declared(in its class). This will mean much easy user semantics.

请注意,这些功能尚未在最新的gcc 4.7中实现,因此您仍然可能会遇到编译错误。

Note that these features have not yet been implemented in latest gcc 4.7, So you might still get compilation errors.

这篇关于为什么我不能在类中初始化非常量静态成员或静态数组?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆