Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Default initialization of class data members in C++11

Tags:

c++

c++11

I'm confused about the default initialization of the class data members. Here is the sample code.

#include <iostream>
#include <vector>

class A {
public:
  int i;
  A() {}
};

A a1;
A aa1[3];
std::vector<A> av1(3);

int main()
{
  A a2;
  A aa2[3];
  std::vector<A> av2(3);
  std::cout << a1.i << " " << a2.i << std::endl;          // 0         undefined
  std::cout << aa1[0].i << " " << aa2[0].i << std::endl;  // 0         undefined
  std::cout << av1[0].i << " " << av2[0].i << std::endl;  // undefined undefined
}

In the code above, only a1.i and aa1[0~2].i are initialized to 0, while others are uninitialized. I don't know why is that happened.

To be specifically, what I already know is that (From "C++ Primer"):

  • The process of initialization is:

    • a1 and a2 are default initialized.
    • every element of aa1 and aa2 are default initialized.
    • every element of av1 and av2 are value initialized.
  • The process of default initialize is:

    • check if the variable is built-in type or class type.
    • for built-in type, if the variable is outside any function body, then it is initialized to 0, else the value is undefined.
    • for class type, if the class has default ctor, then that is called, else it is a compile error.
  • The process of value initialize is:

    • check if the variable is built-in type or class type.
    • for built-in type, it is initialized to 0.
    • for class type, it is default initialized. (Which I think means if the class has default ctor, then that is called, else it is a compile error.)

So that when the ctor A::A() is called, how the data member A::i initialized (I guess it is default initialized)? And why only a1.i and aa1[0~2].i are initialized to 0, while others are uninitialized?

like image 699
Jaege Avatar asked Dec 21 '15 06:12

Jaege


People also ask

Can we initialize data members in a class C?

In C++11, the language has been extended to allow specifying an initializer in the declaration, but this is just a shorthand—the actual initialization still takes place at the top of the constructor. Initialization of data members will also still occur in order of declaration.

Does default constructor initialize members?

Default constructors are one of the special member functions. If no constructors are declared in a class, the compiler provides an implicit inline default constructor. If you rely on an implicit default constructor, be sure to initialize members in the class definition, as shown in the previous example.

How do you initialize a class member?

To initialize a class member variable, put the initialization code in a static initialization block, as the following section shows. To initialize an instance member variable, put the initialization code in a constructor.


3 Answers

when the ctor A::A() is called, how the data member A::i initialized

If no initializer is provided, the rules of default initialization apply. Your constructor does no initialization of A::i so it's left uninitialized; it's value is indeterminate. No doubt about that. Excerpt from the documentation on default initialization:

If T is a class type, the constructors are considered and subjected to overload resolution against the empty argument list. The constructor selected (which is one of the default constructors) is called to provide the initial value for the new object.


why only a1.i and aa1[0~2].i are initialized to 0, while others are uninitialized?

The global data memory is initialized to zero i.e. the whole section is zeroed out and so you see global A::is initialized to 0. Note that the constructor would not be doing this. Excerpt from the documentation:

Static initialization

[...]

2) For all other non-local static and thread-local variables, Zero initialization takes place. In practice, variables that are going to be zero-initialized are placed in the .bss segment of the program image, which occupies no space on disk, and is zeroed out by the OS when loading the program.

However, for the vector, the vector itself is in the non-local static memory while its elements are allocated in free store (heap) and hence their members are uninitialized too.

like image 117
legends2k Avatar answered Oct 12 '22 17:10

legends2k


Global (both static and exported) variables are zero-initialized (in practice, on usual platforms, they are in memory are which is filled with zeros at program start), if they are not explicitly initialized and don't have a constructor.

Items of vector are default-initialized, when you use the constructor you are using in your code.

For a vector class object, both mean a constructor call. But for integers, first means initialized to zero, while latter means initialized with indeterminate value. So the plain int variables in your code are zero-initialized, but the ints in the vector are default initialized.

Some links for reference:

  • http://en.cppreference.com/w/cpp/language/zero_initialization
  • http://en.cppreference.com/w/cpp/language/default_initialization
like image 24
hyde Avatar answered Oct 12 '22 15:10

hyde


You declare a constructor for A, so there is no default initialization of i; that's your responsibility in the constructor. The global variables get initial values of 0 because they're global. All globals are initialized to 0 if they aren't given an initial value by some means.

The local variables and vectors get random data because that's what's in the memory on the stack (for locals) or heap (for the allocated memory that the vector uses) that is being used by those A instances.

like image 1
1201ProgramAlarm Avatar answered Oct 12 '22 15:10

1201ProgramAlarm