0

When I tried to initialize the static member variables at the time of declaration inside the class, compiler is throwing error as expected because we need to explicitly allocate the space for static member variables outside the class. I thought this should be same for static const variables. But to my surprise, initialization of static const member variables inside the class is working fine. Can any one please let me know why normal static member variable initialization is not allowed in the same way?

kadina
  • 5,042
  • 4
  • 42
  • 83

3 Answers3

3

I assume that you meant

// inside class definition block
static const int a = 0;
static int b = 0;       // error 

C++ Standard 9.4.2/4,

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 name- space scope if it is used in the program and the namespace scope definition shall not contain an initializer.

It is specified in standard.

Edit:

as M.M pointed out, above quotation is actually not what the Standard says, and the correct one is C++ Standard 12.2.3.2/3

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 (8.20). The member shall still be defined in a namespace scope if it is odr-used (6.2) in the program and the namespace scope definition shall not contain an initializer. An inline static data member may be defined in the class definition and may specify a brace-or-equal-initializer . If the member is declared with the constexpr specifier, it may be redeclared in namespace scope with no initializer (this usage is deprecated; see D.1). Declarations of other static data members shall not specify a brace-or-equal-initializer.

xvnm
  • 481
  • 4
  • 15
  • 1
    The text you quote does not appear in the current C++ Standard; and section 9.4.2 is about the `switch` statement. You should specify which document you are quoting. (and preferably quote the [latest Standard](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/n4659.pdf)) – M.M May 08 '18 at 21:46
  • @M.M Thx for the pointing out the problem. I thought the quotation was from the Standard because it was already used to answer [another question](https://stackoverflow.com/a/2454082/5406471). I've checked the document you provided and fixed my answer. thx – xvnm May 09 '18 at 08:44
1

One needs a bit of space in memory. Const do not - they can be hard coded.

Ed Heal
  • 59,252
  • 17
  • 87
  • 127
  • It’s not just that they can be hard coded, they MUST be. But you’re right, the space required for const values is known at compile time, and is accounted for in the memory allocated for the program itself, whereas static vars can change during runtime so they must be allocated at runtime. – Brian Driscoll Apr 26 '18 at 01:46
  • @BrianDriscoll - I concur - I was trying not to be too blunt – Ed Heal Apr 26 '18 at 01:47
  • @Brian: What? Just because the value can change doesn't mean the allocation must be dynamic. `char a[4] = { f(), g(), h() }` is always exactly 4 bytes not matter how much work goes into determining its value. Furthermore `const` objects can require dynamic initialization. – Ben Voigt Apr 26 '18 at 01:48
  • @BenVoigt - I have read his comment a few times - I cannot see the word "dynamic" – Ed Heal Apr 26 '18 at 01:50
  • 2
    @BrianDriscoll static const variables may still require a memory address if the `&` operator is used on them, for example, so your logic doesn't hold up. Also, in both cases the space required is known at compile time. – M.M Apr 26 '18 at 01:51
  • @EdHeal: The phrase he used is "at runtime", but `static` allocation is not. – Ben Voigt Apr 26 '18 at 01:51
  • @BenVoigt I was thinking about a simple case like a static string var, whose underlying char array will be resized depending on the assigned value. – Brian Driscoll Apr 26 '18 at 01:53
  • @BrianDriscoll: Whether a `std::string` performs dynamic allocation depends on whether its value fits in small string storage, and not on whether the object is `const`. The `std::string` object itself is allocated statically if it is a static class member. – Ben Voigt Apr 26 '18 at 01:55
  • @BenVoigt et al. The post did not mention `std::string` – Ed Heal Apr 26 '18 at 02:00
  • @EdHeal: Brian did. I think. C-strings don't have "underlying" char arrays, they are char arrays. And the size has to be specified statically, it can't depend on the value let alone be resized. – Ben Voigt Apr 26 '18 at 02:42
  • @BenVoigt - The poster is called kadina not Brian – Ed Heal Apr 26 '18 at 03:38
  • @BenVoigt C strings are sequences of characters , that are usually stored in arrays. The string is not an array any more than `1` is a variable. – M.M May 08 '18 at 21:48
  • `1` is an expression, not a variable. Being a literal does not stop it from also being an expression. C string are sequences of characters, yes. Particularly they are sequences of characters stored consecutively and contiguously and permitting pointer arithmetic; such a sequence is an array. (For example, `struct { char a, b, term; } s = { 'a', 'b', 0 };` does NOT define a C-string, because pointer arithmetic isn't well-defined for moving between elements of a structure, even if they have the same type.) – Ben Voigt May 08 '18 at 22:37
  • @M.M: Please also note that this question is tagged C++, where string literals are expressions of type (`const`) `char[N]` – Ben Voigt May 08 '18 at 22:39
  • @BenVoigt string *literals* are arrays; you said "C-strings" however, not "string literals" – M.M May 08 '18 at 22:55
  • @M.M: The point I was trying to make is that for a C string, the array isn't an underlying implementation detail hidden away, it's directly visible as part of the semantics. There's no abstraction layer on top of the array. The string's an array; the array's a string. [Brian was talking about the string owning and resizing an array.](https://stackoverflow.com/questions/50033574/why-initialization-of-static-member-variable-is-not-allowed-inside-class-but-ini/50033637?noredirect=1#comment87083517_50033637) – Ben Voigt May 08 '18 at 23:02
  • @BenVoigt those comments apply to string literals, not strings. An array is an object, a string isn't. The string can occupy the array in a similar way to how the value `1` can occupy an int variable. – M.M May 08 '18 at 23:19
-1

classes are usually declared in header files. Header files can be included multiple times in body files. If a static member, which needs memory, is defined within a class, than there will be a different copy of such a member in different body files. This will kill the idea of static members.

Constants on the other hand do not use memory and are compile-only constructs. therefore declaring them in the classes does not do any harm.

Serge
  • 11,616
  • 3
  • 18
  • 28
  • _classes are usually defined in header file_ -.> Try declared in the header file – Ed Heal Apr 26 '18 at 02:10
  • Classes *are* usually defined in a header file. – Ben Voigt Apr 26 '18 at 02:52
  • @BenVoigt - Defined is what they do. Declared is what they are supposed to do. Hence being in the header file – Ed Heal Apr 26 '18 at 03:34
  • @EdHeal: Every definition is also a declaration. Typically a header file is the correct place to define a type. It may be preceded by forward declarations to resolve circular dependency problems, but the full type definition also belongs in a header file, with limited exceptions like `FILE` where it is intended for most users to treat it as an opaque type (and even then, it will be defined in a private header file and included into multiple source files operating on it). Lambdas are examples of types which often are defined only in implementation files (and they aren't declared in headers) – Ben Voigt May 08 '18 at 22:43