关于C++11的统一初始化语法示例详解

2020-01-06 17:57:52刘景俊

前言

本文主要给大家介绍了C++11统一初始化语法的相关内容,关于在当前新标准C++11的语法看来,变量合法的初始化器有如下形式:


X a1 {v};
X a2 = {v};
X a3 = v;
X a4(v);

其实,上面第一种和第二种初始化方式在本质上没有任何差别,添加=则是一种习惯上的行为。使用花括号进行的列表初始化语法,其实早在C++98时代就有了,只不过历史上他们只是被用来对数组元素进行初始化操作,以及初始化自定义POD类型的数据(简单理解就是可以memcpy复制对象的类型)。比如:


int v1[] = {1, 2, 3, 4};
int v2[5] = {1,2,3};
char msg = "hello, world!";

在使用列表来初始化数组的时候,如果声明数组的时候没有指定数组尺寸大小,则编译器就使用其列表包含的元素个数自动计算数组的尺寸;如果提供了数组尺寸,但是列表的元素数目小于数组尺寸,则系统会将剩余的元素全部赋值为0。如果是字符数组的话,C++还支持使用字符串常亮来进行初始化。

一、C++11的统一初始化器

在新标准C++11中这个东西使用范围和特性被大大的扩展了,而且已经成为了一个基础而又重要的利器,几乎可以执行任何的初始化操作,所以也被称为”Uniform initialization”,尽管国内还是习惯上称为列表初始化。因为他可以避免传统初始化中的诸多问题和缺陷,所以从Bjarne Stroustrup爷爷的《C++ 程序设计语言》描述口吻看来,列表初始化是被大力推荐使用的,即便用惯旧式初始化的C++程序员初看起来会很不习惯,但C++强烈建议使用上述第一种方式进行统一初始化操作。

C++11还引入了atomic原子类型,这种类型的变量(比如std::atomic)是无法使用传统=方式进行初始化的,只能使用{}或者()方式进行初始化;对于自定义类,如果其非静态成员变量具有默认值,则这个默认值只能用{}或者=进行初始化。总之也只有{}相比于其他类型可以用于任何位置,所以称为统一初始化器也不足为怪了。

防止类型收窄这是列表初始化的一个非常重要的特性,因为C++有很多隐式转换操作的发生,比如:浮点类型隐式转换为整形、长整型转换为短整型导致数据丢失,高精度的数据转换为低精度的数据,但凡是数据转换一次后再向回转换而不能得到原有表示的情况下,都可以称之为类型收窄。类型收窄常常会导致数据精度丢失,甚至潜在有意或无意错误的发生,尤其是那些不喜欢看编译警告的程序员常常会被忽略掉这些提示,而通过列表初始化的语法,编译器在编译期间进行这方面的强制检查,如果发生类型收窄则强制编译失败,从而能够杜绝相关问题的发生。