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

—-想了解关于C++11的统一初始化语法示例详解分享的全部内容且更多的C语言教程关注<计算机技术网>

前言

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

除了上面的优势之外,列表初始化语法还可以杜绝C++重构造语法的阴暗面。C++秉承的一个观念就是任何可以被解释为声明语法的语句都会被解释为声明语句,这会导致调用默认构造函数创建对象的时候被用错。

  Widget w(); // 被解释为函数声明  Widget w{}; // OK

另外一种情况就是在容器使用的时候,也比较容易产生混淆的语义,这个时候使用列表初始初始化语法可以表明我们提供的列表是实际的元素。因为容器类的构造函数具有使用std::initializer_list作为重载的版本,所以如果要显式调用其某个版本的构造函数,就需要使用()来规避std::initializer_list的版本,称之为ctor-resort。

  vector<int> v1{99};   // 一个元素,值为99  vector<int> v2(99);   // 实际是调用构造函数,共99个元素,默认值都是0  vector<string> v2("hello");  // Error,无匹配的构造函数

二、统一初始化器的阴暗面

使用列表初始化语法在绝大多数情况都能胜任,而且工作的很好,但是一旦同std::initializer_list结合起来,它的使用就会让人感觉混淆不清。在auto进行类型自动推导的时候,{}会默认被推导为std::initializer_list,如果这种结果不是你想要的,就需要进行规避以使用其他方式进行初始化操作。

  auto z1 {99}; // initializer_list<int>  auto z2 = 99; // int

如果你认为避免上面那个坑就结束了,呵呵……统一初始化器最大的麻烦还在于其和构造函数的结合。如果某个类的构造函数,其提供了一个接收std::initializer_list作为参数类型的重载版本,那么使用统一初始化句法进行构造对象的时候,编译器将会强烈优先使用具有初始化列表的重载版本。

本文来自网络收集,不代表计算机技术网立场,如涉及侵权请点击右边联系管理员删除。

如若转载,请注明出处:https://www.ctvol.com/c-cdevelopment/488633.html

(0)
上一篇 2020年11月12日
下一篇 2020年11月12日

精彩推荐