// Example program
#include <iostream>
#include <string>
class T{
public:
int x, y;
T(){
std::cout << "T() constr called..." << std::endl;
};
T(int x, int y):x(x),y(y){
std::cout << "T(x,y) constr called..." << std::endl;
}
void inspect(){
std::cout << "T.x: " << this->x << std::endl;
std::cout << "T.y: " << this->y << std::endl;
}
};
int main()
{
T t1(5,6);
t1.inspect();
std::cout << std::endl;
T t2 = {};
t2.inspect();
}
I am getting the following result:
T(x,y) constr called...
T.x: 5
T.y: 6
T() constr called...
T.x: 208787120
T.y: 31385
The members of t2
instance were not zero initialized (what I wanted to achieve). Do I understand it correctly, that if I have a constructor defined, it will not perform a zero initialization?
(I know how to achieve initialization to zero using explicit default values. The problem is why I am not able to do it using the init-list)
List initialization
Otherwise, if the braced-init-list is empty and T is a class type with a default constructor, value-initialization is performed.
Value-initialization
In all cases, if the empty pair of braces {} is used and T is an aggregate type, aggregate-initialization is performed instead of value-initialization.
Aggregate-initialization (it seems this is not my case and therefore it is not initializing members to zero)
An aggregate is one of the following types:
- class type (typically, struct or union), that has
- no user-declared constructors
What would be the simplest and less error-prone modification of legacy code, where I need to solve issues where some class members are used before they are initialized?
Do I understand it correctly, that if I have a constructor defined, it will not perform a zero initialization?
Yes.
Note that T
is not an aggregate because it contains user-provided constructors. As the effect of value initialization:
if T is a class type with no default constructor or with a user-provided or deleted default constructor, the object is default-initialized;
if T is a class type with a default constructor that is neither user-provided nor deleted (that is, it may be a class with an implicitly-defined or defaulted default constructor), the object is zero-initialized and then it is default-initialized if it has a non-trivial default constructor;
T
contains a user-provided default constructor, then #1 (but not #2 performing zero-initialization firstly) is applied.
In default initialization, the user-provided default constructor is used to initialize the object. The default constructor doesn't perform initialization on data members, they are initialized to indeterminate values.