1.用"=":copy initialization,这种初始化形式是从C继承的。此种方式(拷贝初始化)的初始化在现代C+中已不再受欢迎,因为对于某些复杂类型来说,此种方式初始化的效率低于其它形式的初始化。
每当隐式拷贝或转换值时,也会使用拷贝初始化,例如按值将参数传递给函数、按值从函数返回或按值捕获异常时。
2.构造函数初始化:通过括号(parentheses)提供值来声明变量。构造函数初始化和旧的普通初始化方式(=)的区别在于,它总是返回括号中的最后一个值,无论它的大小或符号是什么。
direct initialization:就像拷贝初始化一样,直接初始化在现代C++中已经不再受欢迎,很大程度上是因为被列表初始化所取代。然而,我们现在知道列表初始化有其自身的一些怪癖,因此直接初始化在某些情况下再次得到使用。
当值显式转换为另一种类型时,也会使用直接初始化。
直接初始化不受欢迎的原因之一是它使得很难区分变量和函数:
int x(); // forward declaration of function x
int x(0); // definition of variable x with initializer 0
3.统一初始化(list initialization or uniform initialization or brace initialization):C++中初始化对象的现代方法。用大括号代替括号(curly braces instead of parentheses)。与构造函数初始化不同,此赋值方法只能采用大括号中的一个值,提供多个值将返回编译错误。
列表初始化还有一个额外的好处:列表初始化中的"缩小转换(narrowing conversions,是隐式转换)"格式不正确。这意味着,如果你尝试使用变量无法安全保存的值来初始化变量,则编译器需要生成诊断信息(通常是错误)。
拷贝和直接初始化只会删除小数部分,从而导致值初始化为可变宽度。你的编译器可能会选择性地警告你这一点,因为很少希望丢失数据。但是,通过列表初始化,编译器需要在这种情况下生成诊断。
你可以在通常进行初始化的任何地方使用大括号初始化,例如,作为函数参数或返回值,或者与new关键字一起使用。
Value initialization and zero initialization: 当使用空大括号初始化变量时,将进行值初始化。在大多数情况下,值初始化会将变量初始化为零(或空,如果这更适合给定类型)。在发生归零的情况下,这称为归零初始化。
什么时候应该使用{0}和{}进行初始化:
(1).如果你实际使用该值,请使用显式初始化值。
(2).如果值是临时的并且将被替换,请使用值初始化。
优先选择直接列表初始化(或值初始化)来初始化变量。
以下为测试代码,进行了描述说明
int test_variables_init()
{
int val; // no initializer(default initialization): 在大多数情况下,默认初始化不执行初始化,并且使变量具有不确定的值
// 1.using "="
int val1 = 1; // copy initialization: 这种初始化形式是从C继承的
std::cout << "val1:" << val1 << "\n"; // val1:1
// 2.constructor initialization: parentheses
int val2(2); // direct initialization
std::cout << "val2:" << val2 << "\n"; // val2:2
int val3 = (3);
std::cout << "val3:" << val3 << "\n"; // val3:3
// 构造函数初始化和旧的普通初始化方式(=)的区别在于,它总是返回括号中的最后一个值,无论它的大小或符号是什么
int val4 = (4, 5, 6, 7, -8);
std::cout << "val4:" << val4 << "\n"; // val4:-8
// 3.uniform initialization: curly braces
int val5{ 9 }; // direct list initialization
std::cout << "val5:" << val5 << "\n"; // val5:9
int val6 = { 10 }; // copy list initialization
std::cout << "val6:" << val6 << "\n"; // val6:10
// 与构造函数初始化不同,统一初始化方法只能采用大括号中的一个值,提供多个值将返回编译错误
//int val7 = { 11, 12 }; // error C2440: "初始化": 无法从"initializer list"转换为"int"
int val8{}; // value initialization
int val12{ 0 }; // explicit initialization to value 0
std::cout << "val8:" << val8 << "\n"; // val8:0
// 列表初始化中的"缩小转换(narrowing conversions)"格式不正确
//int val9{ 4.5 }; // error C2397: 从"double"转换到"int"需要收缩转换
int val10 = 4.5; // warning C4244: "初始化": 从"double"转换到"int",可能丢失数据
int val11(4.5); // warning C4244: "初始化": 从"double"转换到"int",可能丢失数据
return 0;
}
执行结果如下图所示:
GitHub:https://github.com/fengbingchun/Messy_Test