当前位置: 首页 > article >正文

C++11之列表初始化

发展历史

C++11是C++的第⼆个主要版本,并且是从C++98起的最重要更新。它引⼊了⼤量更改,标准化了既有实践,并改进了对C++程序员可⽤的抽象。在它最终由ISO在2011年8⽉12⽇采纳前,⼈们曾使⽤名称“C++0x”,因为它曾被期待在2010年之前发布。C++03与C++11期间花了8年时间,故⽽这是迄今为⽌最⻓的版本间隔。从那时起,C++有规律地每3年更新⼀次。

列表初始化

(注意区分列表初始化和初始化列表的概念区别,这俩并非一个东西)

C++98传统的{}

C++98中⼀般数组和结构体可以⽤{}进⾏初始化。

struct Point
{
     int _x;
     int _y;
};

int main()
{
     int array1[] = { 1, 2, 3, 4, 5 };
     int array2[5] = { 0 };
     Point p = { 1, 2 };

     return 0;
}

C++11中的{}

• C++11以后想统⼀初始化⽅式,试图实现⼀切对象皆可⽤{}初始化,{}初始化也叫做列表初始化。

• 内置类型⽀持,⾃定义类型也⽀持,⾃定义类型本质是类型转换,中间会产⽣临时对象,最后优化 了以后变成直接构造。

• {}初始化的过程中,可以省略掉=

• C++11列表初始化的本意是想实现⼀个⼤统⼀的初始化⽅式,其次他在有些场景下带来的不少便 利,如容器push/inset多参数构造的对象时,{}初始化会很⽅便

int main()
{
     // C++98⽀持的 
     int a1[] = { 1, 2, 3, 4, 5 };
     int a2[5] = { 0 };
     Point p = { 1, 2 };
     // C++11⽀持的 
     // 内置类型⽀持 
     int x1 = { 2 };
     // ⾃定义类型⽀持 
     // 这⾥本质是⽤{ 2025, 1, 1}构造⼀个Date临时对象 
     // 临时对象再去拷⻉构造d1,编译器优化后合⼆为⼀变成{ 2025, 1, 1}直接构造初始化d1
     // 运⾏⼀下,我们可以验证上⾯的理论,发现是没调⽤拷⻉构造的 
     Date d1 = { 2025, 1, 1};
    
    // 这⾥d2引⽤的是{ 2024, 7, 25 }构造的临时对象 
    //C++11后支持多参数的隐式类型转换
	 const Date& d2 = { 2024, 7, 25 };//临时对象具有常性,所以定义d2要带有const

    // 需要注意的是C++98⽀持单参数时类型转换,也可以不⽤{} 
     Date d3 = { 2025};//C++11
     Date d4 = 2025;//C++98

    // {}初始化的,可以省略掉= 
     Point p1 { 1, 2 };
     int x2 { 2 };
     Date d6 { 2024, 7, 25 };
     const Date& d7 { 2024, 7, 25 };

    //vector为例
    vector<Date> v;
    v.push_back(d1);
    v.push_back(Date(2025,1,1));
    //比起有名对象和匿名对象传参,{}传参更有性价比
    v.push_back({2025,1,1});
    //map为例
    map<string,string> dict;
    dict.insert({"xxx","yyy"});
    
  
    
     return 0;
}

补充:
  • 匿名对象和临时对象的区别:匿名对象是我们手动创建的,临时对象是编译器生成的,共同特点是都具有常性,都只能给给const引用,不能给普通引用。

  • 这俩转换成汇编指令后都一样

    int x1 = {2};
    int x2 = 2;
    

在这里插入图片描述

迭代器和范围for也是一样的道理。

  •  //注意这个虽然形态一样,但不是列表初始化
        vector<int> v1={1,2,3,4};
        vector<int> v2={11,12,13,14,15,16,17,18,19,20};//可以支持任意多个参数
    

    要支持列表初始化,要有对应参数的构造。而vector可以支持任意多个参数,vector没有全缺省的构造,而是通过C++11的initializer_list支持的。

initializer_list是C++11专门提供的一个类模版

如果把花括号的列表直接给给一个对象,就会将其识别为initializer_list

initializer_list提供的成员有:

在这里插入图片描述

size,begin,end。也就是size和迭代器,还有构造。

initializer_list的底层
initializer_list<int> il1 = {11,12,13,14,15,16,17,18,19,20};
int a1[] = {11,12,13,14,15,16,17,18,19,20};//类似于这个

原理类似:都是在栈上开一段空间,然后把常量数据给拷贝过来。然后initializer_list还有两个指针指向这段空间。

而且通过监视窗口可以看到il1和a1的地址是很接近的。

所以再聊回来vector,vector是怎么支持这个任意个参数初始化的呢?

本质也可以理解成是隐式类型转换

//拷贝+拷贝构造+优化
vector<int> v1 = {11,12,13,14,15,16,17,18,19,20};
//构造
vector<int> v2({11,12,13,14,15,16,17,18,19,20});

其中,下面这行,也就是实参传参给了形参initializer_list<value_type> il

在这里插入图片描述

const vector<int>& v3 = {11,12,13,14,15,16,17,18,19,20};//加const才可以

同样的,也可以去掉赋值符号:

vector<int> v1{11,12,13,14,15,16,17,18,19,20};
const vector<int>& v3{11,12,13,14,15,16,17,18,19,20};

//对比于下面这条,下面的有圆括号,上面的没有圆括号。
//vector<int> v2({11,12,13,14,15,16,17,18,19,20});

最终结果都是构造。

// STL中的容器都增加了⼀个initializer_list的构造 	
vector (initializer_list<value_type> il, const allocator_type& alloc = allocator_type());

list (initializer_list<value_type> il, const allocator_type& alloc = allocator_type());

map (initializer_list<value_type> il,const key_compare& comp = key_compare(),const allocator_type& alloc = allocator_type());
// ...

map的:

//initializer_list + {}pair初始化隐式类型转换
map<string,string> dict = {{"xxx","yyy"},{"sort","zzz"}};

总之,就是一切皆可列表初始化。


http://www.kler.cn/a/526424.html

相关文章:

  • QT串口通信,实现单个温湿度传感器数据的采集
  • 【漫话机器学习系列】068.网格搜索(GridSearch)
  • 初始化mysql报错cannot open shared object file: No such file or directory
  • 最新-CentOS 7 基于1 Panel面板安装 JumpServer 堡垒机
  • ASP.NET代码审计 SQL注入篇(简单记录)
  • AboutDialog组件的功能和用法
  • 不够专业,想更体系化
  • 【视频+图文详解】HTML基础4-html标签的基本使用
  • 2025美赛复盘总结反思(论文手)
  • 第27篇:Python开发进阶:python多线程与多进程编程
  • [LeetCode]day 5 209.长度最小的子数组
  • EWM 变更库存类型
  • Leetcode 3434. Maximum Frequency After Subarray Operation
  • 剑指 Offer II 012. 左右两边子数组的和相等
  • C++初阶 -- 泛型编程(函数模板、类模板)入门
  • Brave132 编译指南 Windows 篇:安装 Visual Studio 2022(二)
  • QT串口通信,实现单个温湿度传感器数据的采集
  • 【初识C语言】作业讲解15课
  • MATLAB语言的测试开发
  • sem_wait的概念和使用案列
  • STM32项目分享:智能温室大棚(APP版)
  • C++ 3
  • ollama指定目录安装
  • 使用Navicat Premium管理数据库时,如何关闭事务默认自动提交功能?
  • openeuler 22.03 lts sp4 使用 cri-o 和 静态 pod 的方式部署 k8s-v1.32.0 高可用集群
  • 【2025最新计算机毕业设计】基于SpringBoot+Vue家政呵护到家护理服务平台(高质量源码,可定制,提供文档,免费部署到本地)