Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Allocation as default initialization

Say I have a struct (or class) with a dynamic array, its length, and a constructor:

struct array {
    int l;
    int* t;
    array(int length);
};

array::array(int length) {
    l=length;
    t=new int[l];
}

I assume everything so far is legal: this is how I would write it (although it maybe not be the only way to do things), but I have seen the following code, that somewhat seems to work:

struct array {
    int l;
    int* t = new int[l];
    array(int length);
}

array::array(int length) {
    l=length;
}

It looks bad, so I wonder if this works out of sheer luck and undefined behaviors, or if there is some internal rule that makes this code work fine.

like image 676
tarulen Avatar asked Jan 28 '19 10:01

tarulen


People also ask

What is default initialisation?

This is the initialization performed when an object is constructed with no initializer.

What is default initialization in Java?

From Java Language Specification. Each class variable, instance variable, or array component is initialized with a default value when it is created (§15.9, §15.10): For type byte, the default value is zero, that is, the value of (byte)0. For type short, the default value is zero, that is, the value of (short)0.

Does C++ have default initialization?

This default initializer propagates into all constructors for that class, even constructors that C++ synthesizes. Initializing members in this way is useful for classes with lots of data members, especially for types such as bool , int , double , and raw pointers.


2 Answers

This code is not correct.

int* t = new int[l]; will happen before l=length;, thus reading the uninitialized variable l. Member initializers are handled before the constructor's body runs.

array::array(int length) : l{length} {}

instead would work because l is declared before t.

However, doing this "by hand" is a bad idea to begin with. You should be using std::vector.

like image 159
Baum mit Augen Avatar answered Oct 23 '22 17:10

Baum mit Augen


The 2nd code snippet might have undefined behavior.

The data members are initialized at the order of how they're declared. For class array, when t is initialized l is not initialized yet. For objects with automatic and dynamic storage duration l will be initialized to indeterminate value, then the usage of l (i.e. new int[l]) leads to UB.

Note that l=length; inside the body of the constructor is just assignment; the initialization of data members has been finished before that.

BTW: With member initializer list the 1st code snippet chould be rewritten as

array::array(int length) : l(length), t(new int[l]) {
}
like image 41
songyuanyao Avatar answered Oct 23 '22 17:10

songyuanyao