1. 使用列表初始化

在c++98/03中,对象的初始化方法有很多种,例如

  1. int ar[3] = {1,2,3};
  2. int arr[] = {1,2,3}; //普通数组
  3. struct A{
  4. int x;
  5. struct B{
  6. int y;
  7. int z;
  8. } b;
  9. }a = {1, {3,4}}; //POD类型,可以直接使用memcpy复制的对象
  10.  
  11. int i = 0;
  12. Foo foo = f;//拷贝初始化
  13.  
  14. int i(0);
  15. Foo f(123); //直接初始化

在c++98/03中,普通数组合POD类型,可以通过初始化列表来进行初始化。c++11中,可以对任意类型对象使用初始化列表进行初始化。 
    列表初始化就是在一个变量后给出一个={},或者直接一个{},括号中含有需要的数据。

  1. class Foo{
  2. public:
  3. Foo(int){};
  4. private:
  5. Foo(const Foo&);
  6. };
  7. int main(){
  8. Foo a1(123);
  9. Foo a2 = 123; //先隐式转换将123转化成一个Foo对象,然后调用operator=进行拷贝构造。
  10. //错误,不能使用拷贝构造函数
  11.  
  12. Foo a3 = {123}; //列表初始化,虽然使用了=,但仍然是列表初始化,私有的拷贝构造无效
  13. Foo a4{123}; //列表初始化
  14. int a5 = {1};
  15. int a6{2};
  16.  
  17. //new 操作符等可以使用圆括号进行初始化的地方,也可以使用列表初始化
  18. int* a = new int{1, 2, 3};
  19. double b = double{12.00};
  20. int* arr = new int[3]{2,4,5};
  21.  
  22. //列表初始化还可以直接使用在函数的返回值上
  23. struct Foo{
  24. Foo(int, double){};
  25. };
  26. Foo func(void){
  27. return {123, 12.00}; //返回构造的Foo对象,使用列表初始化
  28. }
  29. return 0;
  30. }

2. 列表初始化的使用细节

c++11在进行列表初始化的时候,需要进行初始化的对象为聚合体。

c++聚合体

聚合类型的定义: 
(1)类型是一个普通数组 
(2)类型是一个类,而且: 
    (a)无用户自定义的构造函数 
    (b)无私有或保护的非静态数据成员 
    (c)无基类 
    (d)无虚函数 
    (e)不能有{}和=直接初始化的非静态数据成员

  1. 对于情形(e),举个例子
  2. struct ST{
  3. int x;
  4. double y = 0.0;
  5. };
  6. ST s{1, 2.3}; //错误,不能有{}或=直接初始化的非静态数据成员

在c++98/03中,y这种非静态数据成员,本身就不能在声明时进行这种初始化工作,但是在c++11中,非静态数据成员也可以在声明的同时进行初始化工作(即使用{}或=初始化)。

  1. struct ST{
  2. int x;
  3. int y;
  4. ST(int a, int b):x(0), y(0){};
  5. };
  6. ST st{1, 2}; //这里进行初始时,不会进行列表初始化,而是调用的构造函数。因此,st.x = 0, st.y = 0.

聚合类型的定义并不是递归的,即当一个类的非静态成员是非聚合类型时,这个类也可能是聚合类型。

  1. struct ST{
  2. int x;
  3. double y;
  4. private:
  5. int z;
  6. };
  7. ST s{1, 2.4, 1};//错误,不是聚合类型,无法使用列表初始化
  8. struct Foo{
  9. ST st;
  10. int x;
  11. double y;
  12. };
  13. Foo foo{{}, 1, 2.3};//虽然ST并不是一个聚合类型,但是Foo为一个聚合类型。对于非聚合类型成员st初始化时,**使用空的{},相当于调用无参构造函数**

c++11的初始化列表赋值

对于一个聚合类型,使用初始化列表相当于对其中的每个元素分别赋值;而对于非集合类型,则需要先自定义一个合适的构造函数,此时使用初始化列表将调用它对应的构造函数。

3. 初始化列表

c++11中的stl容器拥有和未显示指定长度的数组一样的初始化能力,代码如下:

  1. int arr[]{1,2,3};
  2. std::map<std::string,int>mm={
  3. {"123", 1}, {"hello", 2}, {"fuck", 3}
  4. };
  5. std::set<int> = {1,2,3};

stl中的容器是通过使用std::initializer_list 这个轻量级的模板来实现上述功能。 
std::initializer_list 
(1)它是一个轻量级的容器类型,内部定义了iterator等容器必须的概念 
(2)对于std::initializer_list< T>而言,它可以接受任意长度的初始化列表,但要求元素必须为类型T 
(3)它有三个成员接口: size(), begin(), end() 
(4)它只能被整体初始化或赋值,不能单独修改其中的某个元素(因为由上一条,知道它不提供接口) 
(5)它内部存放的是元素的引用,因此不会进行拷贝操作,所以需要注意在使用的时候保证内部存放的元素有效期

  1. std::initializer_list<int> list = {1,2,3,4};
  2. size_t n = list.size(); // 4
  3. list = {4, 5, 6}; //整体赋值

4. 防止类型收窄

类型收窄指的是导致数据内容发生变化或者精度丢失的隐式类型转换。类型收窄包含如下几种情况: 
(1)从一个浮点数隐式转换到一个整型数 
(2)从高精度浮点数转换为低精度浮点数 
(3)从一个整型数隐式转换为一个浮点数,并且超出了浮点数的表示范围,如 float x= (unsigned long long )-1; 
(4)从一个整型数转换为一个长度较短的整型数,并且超出了长度较短的整型数的表示范围。如char x = 3333; 
    在c++98/03中,出现上面的类型收窄的情况,编译器不会报错。在c++11中,可以通过列表初始化来检查以及防止类型收窄。

  1. int a = 1.1; //可以
  2. int a = {1.1}; //出错

c++11——列表初始化的更多相关文章

  1. C++11 列表初始化

    在我们实际编程中,我们经常会碰到变量初始化的问题,对于不同的变量初始化的手段多种多样,比如说对于一个数组我们可以使用 int arr[] = {1,2,3}的方式初始化,又比如对于一个简单的结构体: ...

  2. C++11的初始化列表

      初始化是一个非常重要的语言特性,最常见的就是对对象进行初始化.在传统 C++ 中,不同的对象有着不同的初始化方法,例如普通数组.POD (plain old data,没有构造.析构和虚函数的类或 ...

  3. c++11之初始化列表

    一.前言     C++的学习中.我想每一个人都被变量定义和申明折磨过,比方我在大学笔试过的几家公司.都考察了const和变量,类型的不同排列组合,让你差别有啥不同.反正在学习C++过程中已经被折磨惯 ...

  4. C++11之列表初始化

    1. 在C++98中,标准允许使用花括号{}来对数组元素进行统一的集合(列表)初始化操作,如:int buf[] = {0};int arr[] = {1,2,3,4,5,6,7,8}; 可是对于自定 ...

  5. C++11常用特性介绍——列表初始化

    一.列表初始化 1)C++11以前,定义初始化的几种不同形式,如下: int data = 0;   //赋值初始化 int data = {0};   //花括号初始化 int data(0); / ...

  6. 第8课 列表初始化(3)_防止类型收窄、explicit关键字

    1. 防止类型收窄 (1)类型收窄:指的是导致数据内容发生变化或者精度丢失的隐式类型转换. (2)类型收窄的几种情况: ①从浮点数隐式转换为整型数,如int i=2.2; ②从高精度浮点数隐式转换为低 ...

  7. initializer_list、初始化列表、列表初始化

    什么是列表初始化 使用一个花括号来初始化变量,表现形式如下: std::vector<int>a{1,2,3,4,5}; 或者 std::vector<int>a = {1,2 ...

  8. 列表初始化 分析initializer_list<T>的实现

    列表初始化(1)_统一初始化 1. 统一初始化(Uniform Initialization) (1)在C++11之前,很多程序员特别是初学者对如何初始化一个变量或对象的问题很容易出现困惑.因为可以用 ...

  9. C++统一初始化语法(列表初始化)

    引言 要是世上不曾存在C++14和C++17该有多好!constexpr是好东西,但是让编译器开发者痛不欲生:新标准库的确好用,但改语法细节未必是明智之举,尤其是3年一次的频繁改动.C++带了太多历史 ...

随机推荐

  1. [转]wait,notify,notifyAll,join,yield,sleep的区别和联系

    1.  Thread.sleep(long) 和Thread.yield()都是Thread类的静态方法,在调用的时候都是Thread.sleep(long)/Thread.yield()的方式进行调 ...

  2. 轻松学习之Linux教程二 一览纵山小:Linux操作系统具体解释

    本系列文章由@uid=hpw" style="padding:0px; margin:0px; color:rgb(255,0,0); text-decoration:none&q ...

  3. 什么是事务(transaction)?它有什么好处

    为了完成对数据的操作,企业应用经常要求并发访问在多个构件之间共享的数据.这些应用在下列条件下应该维护数据的完整性(由应用的商务规则来定义): 分布式访问一个单独的数据资源,以及从一个单独的应用构件访问 ...

  4. imx6 android power off

    调试android4.2的关机功能,希望再按下power按键长时间之后就关机.不弹出选框. 参考链接 http://www.cnblogs.com/sardine/archive/2011/07/26 ...

  5. MFC中的UpdateData()

    UpdateData()是MFC的窗口函数,用来刷新数据的,参数只有一个,默认为TRUE 简单的说: UpdateData(TRUE) == 将控件的值赋值给成员变量, UpdateData(FALS ...

  6. Ubuntu 12.04 root用户登录设置

    Ubuntu 12.04默认是不允许root登录的,在登录窗口只能看到普通用户和访客登录.以普通身份登陆Ubuntu后我们需要做一些修改,普通用户登录后,修改系统配置文件需要切换到超级用户模式,在终端 ...

  7. JavaScript 学习笔记(三)

    本章学习内容: 1.数组的使用 2.类和对象细节. 3.this关键字的使用 4.构造函数,成员函数的使用 1.数组的使用   在任何的语言中,必须要有的就是数组了,有了数组,使得很多操作都变得非常的 ...

  8. java与c#的语法对比

    1,命名空间与包 C#为了把实现相似功能的类组织在一起,引入了命名空间的概念(namespace) Java中与此对应的东西叫做包(package) 2,类的访问控制方面的不同 C#只有两种:publ ...

  9. 访问GitLab的PostgreSQL数据库

    1.登陆gitlab的安装服务查看配置文件 cat /var/opt/gitlab/gitlab-rails/etc/database.yml production: adapter: postgre ...

  10. 解析oracle的rownum

    本人最近在使用oracle的rownum实现分页显示的时候,对rownum做了进一步的分析和研究.现归纳如下,希望能给大家带来收获. 对于rownum来说它是oracle系统顺序分配为从查询返回的行的 ...