Initialization
In a programming context, learned first in CS138 about OOP. This is whenever you use the {}
syntax.
As you’ll see in the slides below, this way, you don’t do a Copy Assignment Operator, but rather directly call the default Constructor when you initialize an object inside the Constructor function.
int x{10};
This can get SUPER confusing with the edge cases.
To not use your mind, just use {}
.
Some resources
- https://blog.tartanllama.xyz/initialization-is-bonkers/
- https://akrzemi1.wordpress.com/2013/09/10/value-initialization-with-c/
C++: Initializer
Types of Initialization
- Zero Initialization
- Value Initialization
- Default Initialization
If no constructor is provided, the compiler will build it for you. For all class member variables not created, it will do the default initialization (allocate the memory space).
We have two types:
- Primitive
- Class
DANGER: Primitive types are NOT always set to 0. In the case of default initialization:
#include <iostream>
using namespace std;
class Foo {
public:
int x;
};
int main() {
Foo foo1;
Foo foo2{};
cout << foo1.x << endl; // garbage value
cout << foo2.x << endl; // 0
}
- I was doing CS247 when I realized that I was wrong about this. The primitive type has garbage value
The initialization sort of has this recursive definition.
Default Initialization
https://en.cppreference.com/w/cpp/language/default_initialization This is the initialization performed when an object is constructed with no initializer.
This simply allocates the memory space. The values will be garbage (some compilers initialize them for optimization..?).
Rule of thumb for default-initialization:
- Built-in types (int, char, float, pointers, etc.) will be left uninitialized, resulting in indeterminate values
- Class types will be default-initialized
Example:
class Foo {
public:
int a;
std::string b;
};
Foo foo; // default initialization
// foo.a has indeterminate value
// foo.b is default-constructed (empty string)
Value Initialization
https://en.cppreference.com/w/cpp/language/value_initialization
This is the initialization performed when an object is constructed with an empty initializer {}
.
Rule of thumb for value initialization:
- Built-in types will be initialized to zero, or null for pointers
- Class types will be default-initialized (NOT value-initialized)
Example:
class Foo {
public:
int a;
std::string b;
};
Foo foo{}; // value initialization
// foo.a is zero
// foo.b is default-constructed (empty string)
Warning
A certain type of initialization does not mean that everything inside the class is initialized the same way.
A class might be value initialized, but member fields are default initialized unless explicitly value intialized.
Consider the example below:
class Member {
public:
int b;
};
class Foo {
public:
int a;
Member m; // m is default initialized
};
Foo foo{}; // value initialized
cout << foo.a << endl; // 0
cout << foo.m.b << endl; // garbage value (default initialization of non-static int)
To fix, you can do something like
class Foo {
public:
Member m;
Foo(): m{} {}
};
So you guarantee m
is always value initialized when Foo
is constructed:
Foo foo;
cout << foo.m.b << endl; // 0
- Notice that even though
foo
is default initialized,Member m
is value initialized
Zero Initialization
https://en.cppreference.com/w/cpp/language/zero_initialization
This is confusing, I don’t quite get the difference with value initialization. Does not have a dedicated syntax in the language.
Rule of thumb for zero initialization:
- For built-in types, zero initialization sets the variable to zero (or null for pointers).
- For class types, zero initialization sets each non-static member to zero.
Unfortunately, there’s no specific syntax for zero-initialization. It typically occurs in specific situations, such as when a global or static variable is declared and not explicitly initialized.
Example:
class Foo {
public:
static int a;
int b;
};
int Foo::a; // Foo::a is zero-initialized because it's a static member
Foo foo; // foo.b has indeterminate value because it's default-initialized
Example
Example taken from CS138
struct A {
A();
T t;
};
A::A() : t{} {} // t is value-initialized (C++11)
struct B {
T t;
};
B::B() {} // t is default-initialized
void main (...) {
T i; // default initialize
T* j = new T; // default initialize
T k{}; // value initialize
T* m = new T{}; // value initialize
}