admin管理员组

文章数量:1431935

We have the fact that a non-inline static data member in a class definition is a non-defining declaration, draft source.

We also have that a non-volatile non-inline const static data member of integral or enumeration type can specify a initializer, draft source

Phrasing it here:

if a non-volatile non-inline const static data member is of integral or enumeration 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 ([expr.const]). The member shall still be defined in a namespace scope if it is odr-used ([basic.def.odr]) in the program and the namespace scope definition shall not contain an initializer.

So I would presume the following is a valid code:

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

The declaration inside of the class definition is not a definition because, again, its a declaration of a non-inline static data member in a class definition.

In Visual Studio the code above retuns me a compilation error:

error C2374: 'a': redefinition; multiple initialization

Questions: What is the practical meaning of a non defining declaration with initializer? Why do the code above is not valid since we only have one definition?

Obs: probably subtle situation here because const I would presume, but the redefinition error is what is getting my attention

We have the fact that a non-inline static data member in a class definition is a non-defining declaration, draft source.

We also have that a non-volatile non-inline const static data member of integral or enumeration type can specify a initializer, draft source

Phrasing it here:

if a non-volatile non-inline const static data member is of integral or enumeration 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 ([expr.const]). The member shall still be defined in a namespace scope if it is odr-used ([basic.def.odr]) in the program and the namespace scope definition shall not contain an initializer.

So I would presume the following is a valid code:

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

The declaration inside of the class definition is not a definition because, again, its a declaration of a non-inline static data member in a class definition.

In Visual Studio the code above retuns me a compilation error:

error C2374: 'a': redefinition; multiple initialization

Questions: What is the practical meaning of a non defining declaration with initializer? Why do the code above is not valid since we only have one definition?

Obs: probably subtle situation here because const I would presume, but the redefinition error is what is getting my attention

Share Improve this question edited Nov 19, 2024 at 1:36 Roman asked Nov 19, 2024 at 1:29 RomanRoman 1656 bronze badges 1
  • The declaration inside of the class definition is not... - this statement does not follow from the excerpt from the standard you provided. It seems that 11.4.9.3(4) says that a constexp must be initialized immediately, and can then be declared again, but without initialization. And for a const, a class variable can be declared without initialization, and initialization can be performed later in some translation unit (the main thing is that there is initialization). But in any case, there must be one initialization. – Halturin Evgeniy Commented Nov 19, 2024 at 3:12
Add a comment  | 

1 Answer 1

Reset to default 4

The error message you're getting is a bit deceiving--it's not really a duplicate definition--but only one of the two can initialize a. So you can have either:

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

...or:

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

...but you can't have initializers in both places.

Also note that since it's a const, you can usually just use:

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

...and as long as you don't use it in a way that requires it to have an address (e.g., take its address or pass it by reference), you don't need an actual definition at all. In this case, it's pretty much equivalent to #define (you can read the name, but to the compiler it's pretty much just a number)--except that unlike #define, it does respect scope and such.

本文标签: cHow do noninline static data member behave in terms of declaration and definitionStack Overflow