C ++ 11: Does the assignment operator provide the POD type, which is the POD, and thus is globally initialized?

Background: I am in a large code environment where the undefined order in which the global constructors are running is problematic. Therefore, I have a custom class that is designed to delay initialization until first use. All his magic happens inside her operators * and operator-> functions; they are the only thing defined. It also saves some state within itself to make the auto-initialization function available. Of course, this state must be POD, so that the entire POD class, so that it can be fully configured before any code starts working, so that all code can use all global variables everywhere, without fear, it is not yet configured .

While someone added a private, never-assigned assignment operator, so the type will never be assigned (it is not intended to be changed in any way). Now someone says the class is broken because it is not a POD. If instead of it is declared, but not defined, I declare it "= delete", I think it is somehow better. And indeed, with this change, the value of std :: is_pod <> :: returns true for the type.

But how does an assignment operator prevent a type from being a POD? I thought that the requirements are that it should have only public data elements, no virtual methods and no constructor or destructor.

And even more important for my situation: is the presence of an undefined class assignment operator from class initialization due to global initialization time together with all other global PODs?

Reduced example:

struct LazyString { const char *c_str; bool has_been_inited; string *lazy_str_do_not_use_directly; string &operator*() { return *get(); } string *operator->() { return get(); } private: string *get() { // The real code uses a mutex, of course, to be thread-safe. if (!has_been_inited) { lazy_str_do_not_use_directly = new string(c_str); has_been_inited = true; } return lazy_str_do_not_use_directly; } // Does this make the class non-POD? // If so, does that mean that global variables of this type // will not be initialized at global-initialization time, that wonderful // moment in time where no code has yet been run? void operator=(const LazyString&); // If I do this instead, it breaks C++03 compatibility, but is this somehow better? void operator=(const LazyString&) = delete; }; LazyString lazy = { "lazy" }; int main(int argc, char *argv[]) { std::cout << *lazy; } 
+5
source share
2 answers

Does the assignment operator provide a POD type

Yes. The type of POD must be trivial; and therefore must be trivially copied; and therefore should not have non-trivial copy or move assignment operators.

Any user-defined operator is nontrivial, so declaring a copy constructor makes the class nontrivial and therefore non-POD.

and is thus globally initialized?

Not. Any instance, POD or not, can be a global variable.

UPDATE . From the comment you wanted to ask:

Can it be statically, but not dynamically initialized?

Yes, since it has a trivial constructor; while the initializer is a constant expression. In your example, { "lazy" } is a constant expression, so LazyString can be statically initialized.

An important feature here is that it has a trivial constructor, and not that it is a POD. POD means that it also meets various other requirements other than initialization.

+6
source

C ++ has several initialization steps for non-local variables with static storage duration (a global variable falls into this category) - regardless of whether the type is POD or not.

  • zero initialization is performed before any other initialization
  • ongoing initialization
  • dynamic initialization

The first two types of initialization must be performed before dynamic initialization. Dynamic initialization is a situation where the initialization order can be difficult to set. Some dynamic initialization is disordered, some are ordered inside a translation unit, etc.

Even if your global variable is not a POD, you can be sure that zero initialization will occur before any dynamic initialization.

See C ++ 11 3.6.2 "Initializing Nonlocal Variables" for details.

+2
source

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


All Articles