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

【C++11】列表初始化【{ }使用详解】

文章目录

  • 前言
  • 1. {}对内置类型和自定义类型
    • 1.1 内置类型
    • 1.2 自定义类型
      • 1.2.1 多参数的隐式类型转化
  • 2. initializer_list
    • 2.1 initializer_list的类型
    • 2.2 在STL中的使用
    • 2.3 区别隐式类型转化和initializer_list

前言

在C++98中,标准允许使用花括号{}数组或者结构体元素进行统一的列表初始值设定。比如:

//C语言风格
struct Point
{int x;int y;
};int main()
{//结构体:struct Point p = { 1, 2 };//数组:int arr[10] = { 1, 2, 3 };return 0;
}

C++委员会认为,利用{}的初始化方式十分“优雅”,于是对于{}的初始化方式进行了升级

下面我们就来认识{}的初始化方式。

1. {}对内置类型和自定义类型

  • C++11扩大了用大括号括起的列表(初始化列表)的使用范围,使其可用于所有的内置类型用户自定义的类型,使用初始化列表时,可添加等号(=),也可不添加。

  • 总结:

    一切皆可使用{}进行初始化

1.1 内置类型

例1:

int main()
{int x = 1; //原始写法//C++11可以的写法:int y = { 1 }; //新写法,有=int z{ 1 }; //新写法,无=int x1{ 1 }, y1{ 2 }; //同类型变量连续定义//对于new来说:int* p = new int(1); //旧写法int* ptr = new int{ 1 }; //新写法return 0;
}

1.2 自定义类型

  • 关于自定义类型的讨论,我们可以从构造函数角度进行学习。

例2:

//已包含头文件
class Point
{
public:Point(int x = 0, int y = 0) //默认构造:_x(x), _y(y){printf("( %d, %d )\n", x, y);  //方便观察}int _x;int _y;
};int main()
{Point p1(1, 1); // 原始写法Point p2 = { 2, 2 }; //C++11有赋值写法 ?Point p3{ 3, 3 }; //C++11无赋值写法return 0;
}
  • 对于自定义类型的构造无一列外需要调用构造函数
    在这里插入图片描述

说明自定义类型使用{}本质也是将参数传递个这个对象的构造函数。

1.2.1 多参数的隐式类型转化

观察上面例2代码:Point p2 = { 2, 2 };是否感觉到特别的熟悉?

我们有如下例3:

class A
{
public:A(int x){cout << x << endl;}
};int main()
{A a = 1;return 0;
}
  • 上面代码中的:A a = 1;是一个单参数的隐式类型转化

    即:编译器先用1构造了一个A类对象,然后再用这个A类对象来拷贝构造给a。但是编译器直接实现优化:1直接构造a对象!

所以现在我们回到刚刚那个问题:Point p2 = { 2, 2 };就是一个隐式类型转化!!!

编译器先利用{2, 2}构造一个Point的临时对象,然后再拷贝构造给p2对象。但是编译器实现了优化,直接利用{2, 2}构造,例如:p1,p3一致。

  • 证明:explicit关键字(禁止隐式类型转化
    在这里插入图片描述

    足以说明p2的构造是采用了隐式类型转化。

explict详情

2. initializer_list

  • initializer_list介绍文档

initializer_list(初始化列表)是C++11引入的一种轻量级模板类,用于简化初始化操作。它允许以统一的方式处理花括号{}列表初始化,常用于构造函数函数参数返回值的初始化场景。

2.1 initializer_list的类型

例4:

//已包含头文件
int main()
{auto il = { 10, 20, 30 };cout << typeid(il).name() << endl;return 0;
}
  • 注:typeid后面会谈到,这里作用:用变量构造一个类,name函数获取变量类型。
    在这里插入图片描述

2.2 在STL中的使用

  • list构造中的initializer_list
  • vector构造中的initializer_list
  • map构造中的initializer_list
  • vector赋值拷贝中的initializer_list
  • ……

例5:

//头文件已正确包含
int main()
{map<string, string> m = { make_pair("香蕉", "banana"), make_pair("苹果", "apple") };cout << m["香蕉"] << endl;return 0;
}

2.3 区别隐式类型转化和initializer_list

例6:

//头文件已正确包含
class Point
{
public:Point(int x = 0, int y = 0) //默认构造:_x(x), _y(y){printf("( %d, %d )\n", x, y);  //方便观察}int _x;int _y;
};int main()
{vector<int> v = { 1,2,2,3,4 }; //代码一Point p = { 1, 2 }; //代码二return 0;
}
  • 代码一:vector<int> v = { 1,2,2,3,4 };是先利用{}进行构造一个initializer_list的对象,再用来构造v对象。

    (自定义的vector没有写initializer_list的构造函数是无法完成构造的,就能说明这一点)

  • 代码二:Point p = { 1, 2 };编译器优化直接构造。

完。

  • 希望这篇文章能够帮助你!
http://www.dtcms.com/a/302820.html

相关文章:

  • Facenet(MTCNN+InceptionResnetV1)人脸考勤项目(有缺点,但可用)
  • 境外期货Level2高频Tick历史行情数据获取与应用指南
  • 基于LangGraph Cli的智能数据分析助手
  • MCU 中的 PWM(脉冲宽度调制)是什么?
  • 八大神经网络的区别
  • Java Stream流的使用
  • Open CV图像基本操作可莉版
  • Linux:线程同步与线程互斥
  • PBR技术
  • 杭州网站建设公司,哪家擅长做多语言外贸站?
  • SpringCloude快速入门
  • JVM 笔记:类加载、内存管理、垃圾收集与垃圾收集器
  • binlog与Maxwell 与 慢查询
  • docker排查OOM
  • 图——邻接表基本操作算法实现
  • 【SpringMVC】SpringMVC的概念、创建及相关配置
  • 对比分析 OceanBase 与数据库中间件
  • Java 数学工具类 Math
  • 6、CentOS 9 安装 Docker
  • 香港Web3媒体Techub News活动大事记:时间线全记录
  • 将 NI Ettus USRP X410 的文件系统恢复出厂设置
  • CMake简单教程
  • 智能指挥调度系统:数字化时代的协同决策中枢
  • 从0到1学PHP(一):PHP 基础入门:开启后端开发之旅
  • 基于 OpenCV 与 sklearn 的数字识别:KNN 算法实践
  • 【CDA干货】金融超市电商App经营数据分析案例
  • 星辰大海的征途:星宸科技的中国芯片突围战
  • 【行测】常识判断1
  • 【Unity笔记03】#if的用法和命名空间
  • EXCEL怎么提取表名