4

I've been reading up on PODs in C++11, and several of the places I've read have said something about PODs supporting static initialization. For example:

On StackOverflow:

The idea of a POD is to capture basically two distinct properties:
1. It supports static initialization, and
2. Compiling a POD in C++ gives you the same memory layout as a struct compiled in C.

(only the bolded part is relavent)

On Wikipedia:

A type that is trivial can be statically initialized.

Apparently I'm not understanding what static initialization is. I thought making a global variable was an example of static initialization, but I can do the following and yet Foo isn't a POD:

#include <type_traits>
#include <iostream>

struct Foo {
  Foo() : x(0), y(0) {}
  int x;
  int y;
};

struct Bar {
  Bar() = default;
  int x;
  int y;
};

// Apparently the following two lines are not "static initialization" because
// Foo is non-POD yet we can still do this:
Foo f;
Bar b;

int main()
{
    if (std::is_pod<Foo>::value) std::cout << "Foo is a POD" << std::endl;
    else                         std::cout << "Foo is *not* a POD" << std::endl;

    if (std::is_pod<Bar>::value) std::cout << "Bar is a POD" << std::endl;
    else                         std::cout << "Bar is *not* a POD" << std::endl;
}

Output:

Foo is *not* a POD
Bar is a POD

So what exactly is static initialization, and how does it relate to trivial classes? Examples would be awesome.

Community
  • 1
  • 1
Cornstalks
  • 37,137
  • 18
  • 79
  • 144
  • A POD cannot have a constructor or destructor as I understand it. Bar doesn't really define a constructor, as it is using the default. – crush Feb 26 '13 at 16:43
  • @crush `nontrivial` ones – Bartek Banachewicz Feb 26 '13 at 16:43
  • @BartekBanachewicz What do you mean? Maybe I need this lesson too! – crush Feb 26 '13 at 16:44
  • @crush: A POD can't have a user-defined constructor (so yes, `Foo` isn't a POD but `Bar` is), but now I'm confused on what static initialization is because I can make global `Foo`s despite it not being a POD, so apparently my understanding of static initialization is wrong. – Cornstalks Feb 26 '13 at 16:45
  • @Cornstalks: You could think about it as being already initialized in the bytes that your executable consists of vs. code needed to run in order to initialize it. – PlasmaHH Feb 26 '13 at 16:46

4 Answers4

5

Static initialization is initialization of some variable with a compile-time value such that the value ends up being "baked into" the executable image (no code needs to be actually run):

struct Foo {
  int x;
  int y;
};

Foo foo = { 0, 1 };

In the above example struct Foo is POD, so the compiler knows that its memory layout is just two integers next to each other. It also knows that foo.x should be initialized to 0 and foo.y to 1. This is enough information to produce a "memory image" of how foo should look at compile time and write it into the executable image.

When the image is later run, the OS loader maps its contents to a memory address and in this way makes foo "alive". The important thing is that the "initialization" of foo has actually completed before the process (which includes your code and also code from the C/C++ runtimes, which get to run first) has had time to execute even a single CPU instruction.

Jon
  • 428,835
  • 81
  • 738
  • 806
  • So, no code needs to run because there is no constructor attempting to initialize the variables? In this example, are x and y uninitialized though? – crush Feb 26 '13 at 16:47
  • @crush: A non-trivial constructor would certainly make the type non-static-initializable. In this example `x` and `y` are initialized to 0 and 1 respectively. I added a few more words, is it better now? – Jon Feb 26 '13 at 16:54
  • Is it allowed for a user to do `Foo foo;` and not provide the initializer? Thanks for your explanations! – crush Feb 26 '13 at 16:57
  • @crush: Yes. But the initialization of the members is now dependent on context. If you declare `Foo foo;` as a global (ie static storage duration) it will be initialized to have both members as zero. This will be "Static initialization". – Martin York Feb 26 '13 at 17:07
  • I think an answer below answered my question: `First, variables with static storage duration are zero-initialized before any other initialization.` – crush Feb 26 '13 at 17:07
5

Initialization of objects with static duration is divided in two passes, static initialization and dynamic initialization (note the abuse of the term static :)).

Dynamic initialization refers to initialization that involves calling functions, and thus must take place at runtime, compared with initialization from literals that can be stored in the executable itself and just loaded.

David Rodríguez - dribeas
  • 204,818
  • 23
  • 294
  • 489
  • Awesome answer +1, well in this world, only few are blessed with gift of teaching and making things awesome to understand, you're one of those gems frankly, I really find your answers very lucid :) – Angelus Mortis Mar 05 '16 at 06:15
5

Static initialization applies to variables with static or thread storage duration. It happens in two phases.

First, variables with static storage duration are zero-initialized before any other initialization.

Then constant initialization is performed. Constant initialization has to be one of the following three possibilities (§3.6.2/2):

  • if each full-expression (including implicit conversions) that appears in the initializer of a reference with static or thread storage duration is a constant expression (5.19) and the reference is bound to an lvalue designating an object with static storage duration or to a temporary (see 12.2);

  • if an object with static or thread storage duration is initialized by a constructor call, if the constructor is a constexpr constructor, if all constructor arguments are constant expressions (including conversions), and if, after function invocation substitution (7.1.5), every constructor call and full-expression in the mem-initializers and in the brace-or-equal-initializers for non-static data members is a constant expression;

  • if an object with static or thread storage duration is not initialized by a constructor call and if every full-expression that appears in its initializer is a constant expression.

Any other initialization (even of a global variable) is dynamic initialization. A compiler is, however, allowed to treat dynamic initialization as if it were static initialization, provided that doing so doesn't change the externally visible effects of the program, assuming it can figure out the correct value (even if that value doesn't officially qualify as a constant expression).

The definition of a constant expression is (unfortunately) rather long and involved. The basic style of the definition is to define a core constant expression as any expression except those fitting a list of exceptions (that, unfortunately, is more than a page long so summarizing it to something that's quick and easy to understand wouldn't be easy).

Community
  • 1
  • 1
Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
-1

Static member initialization occurs in class scope. Therefore, they can access other member data or functions.

That's quoted from MSDN

There is a good example of how it works there.

Sagar V
  • 12,158
  • 7
  • 41
  • 68
Bob
  • 33
  • 1
  • 6
  • Static storage duration is orthogonal to static class members. – underscore_d Jun 28 '17 at 17:43
  • While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes. - [From Review](/review/low-quality-posts/16555793) – iehrlich Jun 29 '17 at 00:10
  • @iehrlich It doesn't answer the question, though. The poster did not actually read the question, just picked out a couple of words, and posted an answer about something totally different that coincidentally uses the same words. – underscore_d Jun 29 '17 at 10:33