C++ common initialization methods

看完了C++ Primer part I,看到了好几个初始化的方式,总是容易忘,翻来翻去也挺麻烦,而且本来也要写笔记,遂记录一下。

Default Initialization

当定义一个变量,但是没有显式地给初始值的时候,就会发生default initialization。

  • built-in types
    • 如果一个built-in type的变量定义在global scope,那么它会被初始化为0
    • 如果它在local scope定义,那么它的值是undefined
  • class types
    • 如果类有default constructor,就会调用这个default constructor
    • 如果类没有定义default constructor,那么编译器会生成一个
      • 如果member有in-class initializer,那么生成的ctor会使用这个initializer
      • 否则,member会进行default initialization
  • 但是对于一个local static变量,如果它的定义没有显式的初始化值,它会进行value initialization
1
2
3
4
5
6
7
// global scope
int x; // default initialization, x initialized to 0.

void func()
{
int x; // defualt initialization, x value undefined.
}
1
2
3
4
5
6
7
8
struct A
{
int x;
double y = 1.0;
};

A a; // no default constructor, compiler generates one
// a.x is default initialized to 0. a.y is initialized with in-class initializer 1.0.

Value Initialization

https://en.cppreference.com/w/cpp/language/value_initialization

value initialization发生在用空的圆括号()或者花括号{}来初始化变量的时候。当创建一个container,只给了size而没给初始值的时候,也会发生value initialization。

  • built-in types:被初始化为0
  • class types:如果类有default constructor,会调用它来初始化;否则是错误
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
int x{}; // x is initialized to 0

// int x1(); // not a variable definition, it's function declaration!

int *px = new int(); // value initialization, px points to a int with value 0

struct MyStruct {
int a;
double b;
};

MyStruct s{}; // `s.a` is 0, `s.b` is 0.0 (members are zero-initialized)

// MyStruct s1(); // not a variable definition, it's a function declaration!!

struct AnotherStruct {
int a;
AnotherStruct(): a() {/* ... */} // a will be value initialized to 0
};
1
2
3
// C++ primer EN p98
vector<int> ivec(10); // ten elements, each initialized to 0
vector<string> svec(10); // ten elements, each an empty string

Direct Initialization

direct initialization用非空的圆括号()或者花括号{}来初始化变量。

1
2
3
4
5
6
7
8
9
10
11
int x(10); // Directly initializes `x` with 10

std::string str("Hello, World!"); // Directly initializes `str` with "Hello, World!"

struct MyStruct {
int a;
double b;
MyStruct(int x, double y) : a(x), b(y) {}
};

MyStruct s(1, 2.5); // Calls MyStruct's constructor

Copy Initialization

https://en.cppreference.com/w/cpp/language/copy_initialization

Copy initialization发生在:

  1. =来初始化变量的时候
  2. 调用函数时,函数的参数pass by value
  3. 函数的返回值return by value
  4. 发生异常时,throw or catch by value
  5. aggregate initialization

对于class types,copy initialization可能会调用copy constructor,也可能会调用(implict) conversion constructor,(还可能会调用move constructor,不过目前还没看到这里,暂且按下不表)。

1
2
MyClass obj1;
MyClass obj2 = obj1; // copy constructor of MyClass will be called
1
2
3
4
5
6
7
8
class MyClass {
public:
MyClass(int x) {
// Conversion constructor
}
};
int num = 42;
MyClass obj = num; // Calls MyClass(int x)

Aggregate

aggregate要么是数组类型,要么是一类特殊的class type。

如果是class type,那么这个class

  • 不能有user-defined consturctor
  • 不能有private和protected member
  • 不能有base class,也就是不能是继承自其他的类

详细的定义在此:https://en.cppreference.com/w/cpp/language/aggregate_initialization

1
2
3
4
5
6
7
8
9
10
11
12
13
14
struct Point {
int x;
int y;
};
int main() {
// Array initialization
int arr[3] = {1, 2, 3}; // Elements `1`, `2`, and `3` are copy-initialized to `arr[0]`, `arr[1]`, and `arr[2]`

// Struct initialization
Point p = {10, 20}; // `10` is copy-initialized to `p.x`, and `20` is copy-initialized to `p.y`

std::cout << "Point: (" << p.x << ", " << p.y << ")" << std::endl;
return 0;
}

List Initialization

list initialization是C++11的新特性,它用花括号{}来初始化对象。之前在value initialization里int x{};MyStruct s{};就用到了list initialization。

list initialization看着和aggregate initialization很像,但是前者不止可以初始化aggregate,还可以用来初始化其他的类型,还可以用在函数的参数。

list initialization也分copy list / direct list initialization,区别和之前 copy / direct initialization 类似。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
struct Point {
int x;
int y;
};

struct Rectangle {
Point topLeft;
Point bottomRight;

Rectangle(int x1, int y1, int x2, int y2)
: topLeft{x1, y1}, bottomRight{x2, y2} {} // List initialization within a constructor
};

int main() {
int x{42}; // Direct list initialization
int y = {42}; // Copy list initialization

Point p{10, 20}; // List initialization of an aggregate
Rectangle r{0, 0, 10, 10}; // List initialization calling a constructor

return 0;
}