Why can't I initialize in-const `const const std :: string` as a static member

I have the following working code:

#include <string> #include <iostream> class A { public: const std::string test = "42"; //static const std::string test = "42"; // fails }; int main(void){ A a; std::cout << a.test << '\n'; } 

Is there a good reason why it is not possible to test a static const ? I understand that before C ++ 11 it was limited by the standard. I thought that C ++ 11 introduced initializations in the class to make it a little more friendly. I also do not have such semantics available for the integral type, since quite a long time.

Of course, it works with initialization outside the class in the form const std::string A::test = "42";

I assume that if you can make it non-static, then the problem lies in one of two things. Initialization of the extra-curricular area (usually const is created at the time the object is created). But I do not think that this is a problem if you create an object independent of any other members of the class. The second has several definitions for a static member. For instance. if it was included in several .cpp files, it landed on several object files, and then the linker would have problems combining these objects (for example, into one executable file), since they would contain copies of the same symbol. As far as I understand, this corresponds exactly to the situation when some grant extra-curricular rights under the class declaration in the heading, and then include this general heading in several places. As far as I remember, this leads to linker errors.

However, now the responsibility for data processing is transferred to the user / programmer. If you want to have a library with static , they need to provide a definition outside the class, compile it into a separate object file, and then link all the other objects to it, therefore, have only one copy of the binary file of the character definition.

I read the answers in Do we need to define static members individually, even if they are initialized inside the class definition? and Why can't I initialize a non-stationary static member or static array in a class? .

I would still like to know:

  • Is this just a standard thing, or is there a deeper reasoning behind it?
  • Is it possible to work with constexpr and user-defined literary mechanisms. Both clang and g ++ say that a variable cannot have a non-literal type. Maybe I can do it. (Maybe for some reason this is also a bad idea).
  • Is it really such a big problem for the linker to include only one copy of the character? Since this is a static const , everything must be binary exact immutable copies.

Plese also comments if I'm missing or don't understand something.

+6
source share
1 answer

Your question has two parts. What does the standard say? And why is that so?

For a static member of type const std::string it must be defined outside the class specifier and have one definition in one of the translation units. This is part of the Unified Definition rule and is specified in Section 3 of the C ++ Standard.

But why?

The problem is that an object with a static storage duration requires a unique static storage in the final image of the program, so it must be associated with one specific translation unit. The class specifier does not have a single translation unit at home, it simply determines the type (which should be identically defined in all translation units where it is used).

The reason the constant does not need memory is because the compiler uses it as a constant expression and is built into the point of use. He never gets into the image of the program.

However, a complex type, such as std::string , with a static storage duration, requires storage, even if they are const . This is due to the fact that they may need dynamic initialization (their constructor is called before entering the main one).

It can be argued that the compiler must store information about objects with a static storage duration in each translation unit where they are used, and then the linker must combine these definitions during the link into one object in the program image. My guess why this is not done is that the linker will need too much intelligence.

+2
source

Source: https://habr.com/ru/post/948270/


All Articles