What special rules do C ++ apply to static constant integral types?

I got the impression that C ++ applies the same special rules to a static const integral type, regardless of whether it is declared in the namespace scope or declared in the / struct / union class.

Now I think I was taught Bad Things by inappropriate compilers.

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

Besides the obvious difference in scope, How are A and s::A different?

  • ... when will their use be replaced by their literal meaning?
  • ... when can I get his address?
  • ... when do I need to define them separately?

I am particularly interested in learning about C ++ 03.

+6
source share
2 answers

The static does not mean the same thing in a class and in a namespace. In fact, it is used in the namespace area is deprecated.

When declaring a variable in the scope of the class, static means that there will be one instance of the variable, with a static storage duration and lifetime. A declaration within a class is not a definition; if a variable is used, it must be defined in one (and only one) translation unit; if this is not determined by undefined behavior. (In practice, depending on usage, either everything will work fine, or you will get an error from the linker.) Note that if the declaration for a const contains initialization, this is not considered used if it is used in a context that requires constant integral expression (e.g. C-style dimension array). The simplest and most reliable thing is to simply identify it somewhere.

When declaring a variable in the namespace scope, static means that the name has an internal relationship, not an external one; with or without static , a declaration is a definition (so there should not be another definition in a program). In C ++ 03, this use is deprecated; use an unnamed namespace instead. Note also that if the variable itself is const (the upper level is const), then by default it has an internal connection, so static does not have an effect at all. (If you need a const variable with an external connection, make it a member of the class or define it explicitly extern , using the initializer to make this definition, not just a declaration.)

+6
source

What is the difference between A and s::A ?

The biggest difference is that the declaration of A also a definition, while the definition of s::A is not. I'm not sure what you mean by "special rules", but static has a different meaning in each case.

In the namespace area, it gives an internal connection so that the object is not visible outside the current translation unit. Note that static is redundant here, because by default, constant variables in the namespace have internal bindings.

In the realm of a class, this means that there is a separate object independent of any instance of the class.

when will their use be replaced by their literal meaning?

Since both are integral constants with an initializer in the declaration, both can be used in constant expressions, and the compiler can replace their values ​​with compile-time constants.

Perhaps a more appropriate question is: when is a definition needed?

In C ++ 11, it is required if the variable is used by odr - roughly speaking, if you are doing something that requires the address of a variable, not its value.

In C ++ 03, I think it was necessary if the variable is used at all, although no diagnostics are required, and many compilers will not complain if you use only its value. I could be wrong; the old rules were pretty confusing, and I'm happy that I could forget them now.

when can i get his address?

This requires that the variable has a definition in both C ++ 03 and C ++ 11. In the definition, memory is allocated for the variable, so it has an address.

When do I need to identify them separately?

Declaring a variable in a namespace scope is also a definition unless you declare it extern ; therefore, your first variable does not need a separate definition.

Declaring a variable in a class is not a definition; therefore, your second variable needs a separate definition in C ++ 03, and in C ++ 11 if it is used by odr.

0
source

All Articles