初始化的概念
初始化(initialized):当对象在创建时获得了一个特定的值,称为对这个对象的初始化。
初始化后值未定义的情况有2种:
- 定义在函数内部的未被显示初始化的内置类型对象;
- 未被显示初始化的动态分配的内置类型对象。
其他相关概念:类内初始值、构造函数初始值列表。
在构造函数函数体内对变量的操作为赋值,不是初始化。
初始化的含义是创建变量赋予其一个初始值,而赋值的含义是把当前值擦除,而以一个新值来替代。
struct Sales_data {
Sales_data() = default;
Sales_data(const std::string &s): bookNo(s) {} //冒号后为构造函数初始值列表
std::string bookNo;
unsigned units_sold = 0; // 类内初始值
double revenue = 0.0; // 类内初始值
};
初始化的分类
对象初始化可以分为直接初始化、拷贝初始化、默认初始化、值初始化、列表初始化。直接初始化和拷贝初始化是通过构造函数和拷贝构造函数实现的。
string str1(10,'9');//直接初始化,没有=号
string str2(str1);//直接初始化,没有=号
string str3 = str1;//拷贝初始化,使用=号
string *ps = new string;//类类型使用默认构造函数,默认初始化为空string
string *ps2 = new string();//值初始化为空string
int *pi1 = new int;//默认初始化,值未定义
int *pi2 = new int();//值初始化,为0
int a{0}, b = {0};//列表初始化。带花括号{}
1,直接初始化
不使用等号则使用的是直接初始化。
string str1(10,'9');//直接初始化
string str2(str1);//直接初始化
string str3 = str1;//拷贝初始化
2,拷贝初始化
使用等号(=)初始化一个变量,实际上执行的是拷贝初始化。
拷贝初始化不仅在我们使用=定义变量时会发生,在下列情况也会发生:
- 将一个对象作为实参传递给一个非引用类型的形参。
- 从一个返回类型为非引用类型的函数返回一个对象。
3,默认初始化
如果定义变量时没有指定初值,则变量被默认初始化。
默认值到底是什么由变量类型决定,同时定义变量的位置也会对此有影响。如果是内置类型的变量未被显示初始化,它的值由定义的位置决定。
定义在任何函数体之外的变量被初始化为0。
定义在函数体内部的内置类型变量将不被初始化,一个未被初始化的内置类型变量时未定义的。static的除外,static的变量会执行值初始化,值为0。
默认情况下,动态分配的对象也是默认初始化的,这意味着内置类型或组合类型的对象的值将是未定义的。而类类型对象将使用默认构造函数进行初始化:
int *pi = new int;//pi指向一个动态分配的,未初始化的无名对象
string *ps = new string;//默认初始化为空string
4,值初始化
只提供vector对象容纳的元素数量而去忽略元素的初始值,此时库会创建一个值初始化的元素初值,并把它赋予容器中的所有元素。
vector<int> v1(10);//值初始化。10个元素,每个元素的初始化为0
vector<string> v2(10);//值初始化。10个元素,每个元素都为空
vector<int> v3{10};//列表初始化。v2有1个元素,该元素的值是10
vector<int> v4(10, 1);//直接初始化。v3有10个元素,每个的值都是1
vector<int> v5{10, 1};//列表初始化。v4有2个元素,值分别是10和1
使用new动态分配和初始化对象
我们可以使用直接初始化方式来初始化一个动态分配的对象:
int *pi = new int(1024);//pi指向的对象的值为1024
string *ps = new string(10,'9');//*ps为"9999999999"
也可以对动态分配的对象进行值初始化,只需要在类型名后跟一对空括号即可:
string *ps1 = new string;//默认初始化为空string
string *ps2 = new string();//值初始化为空string
int *pi1 = new int;//默认初始化
int *pi2 = new int();//值初始化为0
5,列表初始化(C++11新标准)
使用花括号{}为对象赋初值,称为列表初始化。当用于内置类型的变量时,这种初始化形式有一个重要特点:如果使用列表初始化且初始值存在丢失信息的风险,编译器会报错。
long double ld = 3.1415926536;
int a{ld}, b = {ld}; //列表初始化。错误:转换未执行,因存在丢失信息的危险
int c(ld); // 直接初始化。正确:转换执行,且丢失部分值
int d = ld; // 拷贝初始化。正确:转换执行,且丢失部分值
注:
上述内容参考自C++ Primer(第5版)以及该博客https://blog.csdn.net/yang20141109/article/details/50374696
版权声明:本文为qq_25635285原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。