我们知道,C和C++因为性能的考量,只对静态/全局变量进行初始化,其它如栈、堆上的数据的初始化时机由程序员自行选择。(静态/全局变量的特权在于其数量少,重要性高)
1 初始化VS赋值
一个数据在定义时就直接设置成某值,就叫“初始化”;而一个数据已经存在后才被设置成某值,叫“赋值”。
2 构造式初始化
使用小括号“()”可以对基本数据类型、有构造函数的类的对象进行构造式初始化。
struct Point{ Point(int a, int b){ x=a;y=b;} int x,y; }; int i(5); Point point(3,4);
3 赋值式初始化
尽管构造式初始化非常有格调,但对于简单变量,更常见的还是采用等号完成初始化:
int i = 5; float f = 12.3F; char c = 'c';
赋值式初始化的限制:
3.1 如果一个对象的构造函数有两个入参呢?赋值式初始化不支持需要多个入参的构造。
3.2 赋值式初始化不支持堆对象的双重初始化:
int* p = new int(5);
3.3 类和结构体的赋值式初始化的具体实现还取决于编译器
struct A{ A(int i){x=i;} int x; };
如果编译器未做优化处理,对于:
A a=5;
编译器会做两步操作:
A tmp(5); // 先构造一个临时对象
A a(tmp); // 再从临时对象复制到目标对象
如果编译器有做优化,则可以一步到位,直接用构造式初始化代替赋值式初始化:
A a(5);
4 列表式初始化
列表式初始化使用大括号{},如:
int main() { struct Point{ Point(int a, int b){ x=a;y=b;} int x,y; }; int i{5}; Point point{3,4}; int arr[5]{1,2,3,4,5}; int* parr = new int [5]{1,2,3,4,5};
一些类的特殊成员在构造函数中初始化时,编译器强制要求使用构造式初始化,称为成员初始化列表,如对象成员、调用基类构造函数初始基类成员、const和引用数据成员。
数量不定的初始化列表:
std::vector<int> vec{23,12,45,56};
5 成员声明式初始化(C++11)
C++11支持类或结构体在数据成员声明时即初始化:
struct Point{ int x = 3; int y = 4; };
-End-