C++进阶 —— 列表初始化(C++11新特性)

【C++11保姆级教程】列表初始化(Literal types)和委派构造函数(delegating)) C++11引入了许多新的语言特性和标准库扩展,这些变化使得C++编程更加强大和便捷。其中,列表初始化和委派构造函数是C++11中引入的两个重要特性。本文将深入探讨列表初始化和委派构造函数的概念、用法以及示例代码,帮助读者更好地理解和应用这些特性。在上述示例中,我们定义了一个Rectangle(矩形)类,它具有三个构造函数:默认构造函数、边长相同的构造函数和指定宽高的构造函数。在默认构造函数和边长相同的构造函数中,我们使用委派构造函数的方式,将初始化逻辑委派给指定宽高的构造函数。 阅读详情

目录

一,列表初始化

{ }初始化

优势

使用场景

二,类模板列表初始化

库模板初始化列表实现

模拟模板初始化列表实现


        在2003年C++标准委员会曾经提交了一份技术勘误表(简称TC1),使得C++03这个名字已经取代了C++98称为C++11之前的最新C++标准名称;不过由于TC1主要是对C++98标准中的漏洞进行修复,语言的核心部分则没有改动,因此人们习惯的把两个标准合称为C++98/03标准;从C++0x到C++11,C++标准十年磨一剑,第二个真正意义上的标准姗姗来迟; 相比于C++98/03,C++11则带来了数量可观的变化,其中包含了约140个新特性,以及对C++03标准中约600个缺陷的修正,这使得C++11更像是从C++98/03中孕育出的一种新语言;相比较而言,C++11能更好地用于系统开放和库开发,语法更加泛化和简单化,更加稳定和安全,不仅功能强大,而且能提升程序员的开发效率;

一,列表初始化

        列表初始化(List Initialization)是一种 C++11 引入的一种统一的初始化语法,可用来初始化各种类型的对象,包括数组、结构体、类以及容器等;提供了更安全、更一致的初始化方式,能够应用于各种初始化场景;

        具体来说,列表初始化使用花括号 {} 将一组值括起来,用逗号分隔各个元素,形成一个初始化列表;注意与类成员初始化列表(如:_a(a))的区别;

{ }初始化

        在C++98中,标准允许使用{}对数组或结构体元素进行统一的列表初始化设定;但对一些自定义类型不可这样使用,无法编译,会导致如每次定义vector时,都需要先定义vector,在循环对其赋初始值,非常不方便;

//C环境
/*struct Point
{
    int _x, _y;
};*/
int arr[] = {1, 2, 3, 4, 5};
int arr[5] = {0};
Point p = { 1, 2 };

//c++98中不可这样使用,需循环赋值
vector<int> v = {1, 2, 3, 4, 5};

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

编译器会对大括号中的元素进行类型检查,不符合要求即报错;

  • 元素类型与被初始化对象类型匹配;
  • 对自定义类型大括号内的元素个数与被初始化对象构造函数参数个数匹配;
//内置类型
int x = 10;
int x = {10};
int x{10};

int x = 1+2;
int x = {1+2};
int x{1+2};

//数组
int arr[5] = {1,2,3,4,5};
int arr[] = {1,2,3,4,5};
int arr[]{1,2,3,4,5};

//动态数组,C++98不支持
int* parr = new int[5]{1,2,3,4,5};
int* parr = new int[]{1,2,3,4,5};

//标准容器,调用initializer list构造函数
vector<int> v1{ 1, 2, 3, 4, 5 };
vector<int> v2={ 1, 2, 3, 4, 5 };
map<int, int> m{{1,1},{2,2},{3,3},{4,4}};

        对于内置类型,列表初始化在某些情况下可能会导致不同的行为,特别是当涉及到类型推导;通常推荐使用直接初始化(如int x = 5)或列表初始化(C++11引入的int x{5});

auto x = {5}; //实际类型为std::initializer_list<int>
int x = 5; //直接初始化
int x{5};

优势

  • 统一的初始化语法,可用于几乎所有初始化场景;
// 变量初始化
int x{5};
// 动态分配内存
int* p = new int{10};
// 函数返回值
std::vector<int> makeVec() {
    return {1, 2, 3};  // 返回列表初始化
}
// 类成员初始化
class Widget {
    std::vector<int> data{1, 2, 3};  // 成员初始化
};
  • 防止窄化转换(Narrowing Conversion),即不允许可能导致数据丢失的隐式类型转换;
int a = 3.14;    // 警告但允许,a=3
int b{3.14};     // 错误!窄化转换从double到int

char c{1000};    // 错误!窄化转换(如果char是8位)
unsigned u{-1};  // 错误!窄化转换
  • 避免最令人烦恼的解析(Most Vexing Parse);
class Timer;
// 传统语法可能被解析为函数声明
Timer t();  // 函数声明,返回Timer对象
// 列表初始化明确表示对象初始化
Timer t{};  // 明确初始化Timer对象

使用场景

  • 容器初的始化;

//标准容器,调用initializer list构造函数
vector<int> v1{ 1, 2, 3, 4, 5 };
vector<int> v2={ 1, 2, 3, 4, 5 };
map<int, int> m{{1,1},{2,2},{3,3},{4,4}};
  • 自定义类型的初始化,会尝试调用匹配的构造函数;

class Point
{
public:
	Point(int x=0,int y=0)
		:_x(x), _y(y)
	{}
private:
	int _x, _y;
};

int main()
{
    //以下等价,构造函数参数列表与大括号内元素个数一致
	Point p(1, 2);
	Point p1 = { 1, 2 };   
    Point p2{ 1, 2 };
}

  • 聚合类初始化,即没有用户定义的构造函数、没有私有/受保护的非静态成员等);

//struct或class
struct Aggregate {
    int x;
    double y;
    std::string name;
};

Aggregate a{10, 3.14, "test"};  // 聚合初始化

二,类模板列表初始化

  • 要支持初始化列表,需给该类(模板类)添加一个带有initializer_list类型参数的构造函数;
    • 所有现代STL容器都支持initializer_list构造函数,方便实现任意数量参数的函数;
      • 如序列式容器(array、vector、deque、list、forward_list),关联式容器(set/multiset、map/multimap、unordered_set/unordered_multiset、unordered_map/unordered_multimap);
      • 容器适配器(stack、queue、priority_queue)不支持,但可在构造时传递容器;
    • initializer_list是轻量级容器,不管理内存,只是底层数组的视图;
    • 元素是const,不能修改;
    • 廉价的拷贝,拷贝操作通常共享底层数据;
    • 比普通构造函数优先级更高;
  • initializer_list是系统自定义的类模板,该类模板中主要有三个方法:
    • begin()、end()迭代器;
    • 获取区间中元素个数的方法size();

  • Initializer list 类型用于访问初始化列表中的值;
  • Initializer list 类型对象由编译器从初始化列表声明(用大括号括起来的逗号分隔的元素列表)中自动构造,即{value1,value2,...}会自动构造一个Initializer list对象;
//库定义
template <class _Elem>
class initializer_list 
{
public:
    ...
    constexpr initializer_list() noexcept : _First(nullptr), _Last(nullptr) {}
    constexpr initializer_list(const _Elem* _First_arg, const _Elem* _Last_arg) noexcept
        : _First(_First_arg), _Last(_Last_arg) {}
    _NODISCARD constexpr const _Elem* begin() const noexcept {return _First;}
    _NODISCARD constexpr const _Elem* end() const noexcept {return _Last;}
    _NODISCARD constexpr size_t size() const noexcept {return static_cast<size_t>(_Last - _First);}
private:
    const _Elem* _First;
    const _Elem* _Last;
};
std::initializer_list<int> li = { 1,2,3,4 };
std::cout << li.size() << std::endl;
for (auto i = li.begin(); i != li.end(); i++)
{
	std::cout << *i << std::endl;
}
template<class T>
class Point
{
public:
	Point(T x, T y)
		:_x(x), _y(y)
	{
		cout << "Point(int x = 0, int y = 0)" << endl;
	}

	Point(std::initializer_list<T> li)
	{
		_x = *(li.begin());
		_y = *(li.begin()+1);
		cout << "Point(std::initialier_list<T> li)" << endl;
	}
private:
	T _x, _y;
};

int main()
{
	Point<int> p = { 1,2 }; //优先使用Point(std::initializer_list<T> li)
}

库模板初始化列表构造函数的实现

  • 调用对应的初始化列表构造函数,然后将初始化列表值循环将元素赋值到对象内;
//vector库模板,初始化列表构造函数	
_CONSTEXPR20_CONTAINER vector(initializer_list<_Ty> _Ilist, const _Alloc& _Al = _Alloc())
	: _Mypair(_One_then_variadic_args_t{}, _Al)
{
	auto&& _Alproxy = _GET_PROXY_ALLOCATOR(_Alty, _Getal());
	_Container_proxy_ptr<_Alty> _Proxy(_Alproxy, _Mypair._Myval2);
    //初始化列表赋值
	_Range_construct_or_tidy(_Ilist.begin(), _Ilist.end(), random_access_iterator_tag{});
	_Proxy._Release();
}

template <class _Iter>
_CONSTEXPR20_CONTAINER void _Range_construct_or_tidy(_Iter _First, _Iter _Last, input_iterator_tag) {
	_Tidy_guard<vector> _Guard{ this };
	for (; _First != _Last; ++_First) {
		emplace_back(*_First); // performance note: emplace_back()'s strong guarantee is unnecessary here
	}
	_Guard._Target = nullptr;
}

模拟模板初始化列表实现

#include<initializer_list>
template<class T>
class MyVector
{
public:
	MyVector(std::initializer_list<T> lt)
		:_capacity(lt.size())
		,_size(0)
	{
		_array = new T[_capacity];
		for (auto e : lt)
			_array[_size++] = e;
	}
	
	MyVector<T>& operator=(std::initializer_list<T> lt)
	{
		delete[] _array;

        _capacity = lt.size();
        _array = new T[_capacity];
		_size = 0;
		for (auto e : lt)
			_array[_size++] = e;

		return *this;
	}
private:
	T* _array;
	size_t _capacity;
	size_t _size;
};

int main()
{
    //以下三种形式等价
    MyVector<int> v1({ 1,2,3 });
	MyVector<int> v2 = { 1,2,3 };
	MyVector<int> v3{ 1,2,3 };
    //调用operator=
	v1 = { 3,2,1 };
	return 0;
}

C++中的列表(List)数据结构详解及示例代码 在C++编程中,列表(List)是一种常用的数据结构,用于存储一系列元素。本文将详细介绍C++中列表的使用方法,并提供相应的示例代码。通过以上示例,我们已经了解了C++中列表的基本用法。在实际应用中,我们可以根据具体需求选择不同的列表操作来满足我们的编程需求。要访问列表中的元素,可以使用迭代器(iterator)。在上面的示例中,我们创建了一个整数类型的列表,并添加了三个元素:10、20和30。在上面的代码中,我们分别从列表的末尾和开头删除了一个元素。在上面的示例中,我们使用下标运算符访问了列表。 阅读详情

相关推荐

C++11新特性之列表初始化

文章目录**1、统一的初始化方法****2、列表初始化的一些使用细节****3、初始化列表****4、列表初始化防止类型收窄** 在我们实际编程中,我们经常会碰到变量初始化的问题,对于不同的变量初始化的手段多种多样,比如说对于一个数组我们可以使用 int arr[] = {1,2,3}的方式初始化,又比如对于一个简单的结构体: struct A { int x; int y; }a = {1,2}; 这些不同的初始化方法都有各自的适用范围和作用,且对于类来说不能用这种初始化的方法,最主要的是没有一种可

二进制君 9232

【C++】-- 初始化列表

初始化列表:以一个冒号开始,接着是一个以逗号分隔的数据成员列表,每个"成员变量"后面跟一个放在括 号中的初始值或表达式。

局部变量和全局变量 2万+

Zabbix7.4监控系统在Rocky Linux10.0上的完整部署流程(含MariaDB配置)

本文详细介绍了在Rocky Linux 10.0操作系统上部署企业级监控系统Zabbix 7.4的完整流程,并重点阐述了与MariaDB数据库的深度集成与性能优化配置。内容涵盖从系统环境准备、数据库安装与安全加固、Zabbix核心组件部署,到服务配置、Web界面初始化以及生产环境高级调优的全方位实战指南,旨在帮助用户构建稳定高效的监控平台。

weixin_29200741的博客 328

C++基础——初始化列表

C++初始化列表讲解

weixin_69283129的博客 6540

Linux下基于AHCI controller模块实现SATA Platform驱动附代码详细流程

本文主要是针对ARM A55集成了AHSATA controller模块开发sata驱动,通过Platform的形式在linux识别到SSD,本文详细讲述整个开发过程,同时对SATA Platform驱动进行讲解。1、配置SATA Phy的初始化;2、打开SATA Platform相关编译开关;3、配置设备树;4、linux启动识盘。

Luckiers的博客 2497

机械臂标准DH建模及正运动学分析(以IRB4600型工业机械臂为例)

对于工业机械臂而言,运动学是不考虑力学特性的情况下对机械臂的几何参数与其位置、速度、加速度等运动特性的关系研究。DH建模是运动学的基础,全称为Denavit-Hartenberg建模方法,是一种广泛应用于机器人运动学中的建模技术。该方法通过在每个连杆上建立坐标系,并利用齐次坐标变换来实现连杆之间的坐标转换。通过依次变换,可以推导出末端执行器相对于基坐标系的位姿,从而建立机器人的运动学方程。以IRB4600型六自由度工业机械臂为例,选择标准DH建模方法,建立其正运动学模型。

chen_mp的博客 1万+

【C++进阶】C++11的新特性 | 列表初始化 | 可变模板参数 | 新的类功能

本文介绍了C++11标准中的新特性,重点讲解了列表初始化的相关内容。 在列表初始化方面,C++11扩展了C++98中{}初始化的使用范围,使其可以用于一切对象的初始化,包括内置类型和自定义类型。文章通过代码示例展示了如何使用{}初始化各种类型对象,并解释了背后的优化原理。 特别介绍了std::initializer_list类,这是STL容器支持列表初始化的关键。通过initializer_list,容器可以方便地接受任意多个值的初始化列表。文章还展示了容器如何利用initializer_list实现初始化

Linux、C++、图形软件开发等。不一定每次都能写出完美的代码,但会认真搞懂每一个问题。 1409

生成式引擎优化(GEO)标准化操作流程:构建高效AI生成系统的全链路指南

GEO是针对生成式AI的内容优化策略,通过提升内容在AI生成答案中的引用优先级实现品牌传播。相比传统SEO,GEO使内容直接嵌入AI答案,无需用户点击链接。核心流程包括:1)逆向拆解AI问答场景,结构化知识资产;2)生产权威内容(白皮书、专利数据)和算法适配内容(PCOE模板);3)技术实现(数据投喂、模型微调);4)331渠道分发策略;5)效果监控与动态防御。需注意采用结构化数据标记、主动提交训练数据,并避免简单复制SEO策略。2025版强调内容权威性和语义优化,通过AI原生内容工程实现高效曝光。

解锁AI流量新红利!🚀 GEO优化(生成引擎优化)助您掌控AI搜索,让AI成为您的品牌最佳代言人! 1160

【初阶与进阶C++详解】第二十二篇:C++11新特性(列表初始化+变量类型推到+右值引用+新增默认成员函数+可变模板参数+lambda表达式+包装器function_bind)

C++11是2011年更新的C++新语法,C++11能更好地用于系统开发和库开发、语法更加泛华和简单化、更加稳定和安全,不仅功能更强大,而且能提升程序员的开发效率。[capture-list]捕捉列表,用于编译器判断是否是lambda表达式,同时捕捉该表达式所在域的变量以供函数使用(parameters)参数,和函数的参数一致。如果不需要传参则可连带()一起省略mutable默认情况下捕捉列表捕捉的参数是const修饰的,该关键字的作用是取消const使其可修改。

YQ20210216的博客 996

手把手教会你用yolov8从环境配置到检测任务实战

做本文章前,我浏览过很多网上资料,我发现他们总是写的含糊不清,而且实际操作起来就会有各种各样的问题,要么就是根本不适合一些小白,所以我在这里写一篇完全针对小白的yolo从入门到实战。看完本文章后大家都可以实现下图效果,数字识别是一种比较简单的检测任务,其他识别任务学完本例也能够一通百通,大家边做边学,更好的体会yolo的神奇之处。

KevenDuan的博客 2871

IEC61850客户端连接实战:CMS vs MMS协议抓包对比与性能初探(基于YX-PIS协议栈)

本文深入探讨了IEC61850客户端连接中CMS与MMS协议的抓包对比与性能优化。通过Wireshark抓包分析、协议栈配置实战和性能基准测试,揭示了两种协议在连接建立、数据交互和性能调优方面的关键差异,为智能电网自动化系统的协议选择提供了实用指南。

weixin_29209805的博客 215

C++进阶知识复习 16~30

C++进阶知识总结2

小萌新的博客 1061

关于使用EB tresos出现无法激活的情况解决

我在安装eb studio时就是在激活方面有问题导致无法使用,下面讲解出现了什么问题以及我如何去解除的。EB安装完成时需要激活才能使用的,不然都打开或者建立不了工程,一直都是报的dns服务器错误,好的,那我改dns服务器地址。填写dns服务器地址,也可以换成别的,自己百度一下适合自己的。这是解决方案哈哈哈哈。

weixin_43673603的博客 6179

C++进阶:C++11相关

本文摘要:C++11新特性解析 本文系统讲解了C++11中的关键新特性: 列表初始化:统一了内置类型和自定义类型的初始化方式,引入initializer_list支持容器初始化 右值引用:区分左值/右值,通过移动语义优化资源管理,减少拷贝开销 类型分类:细化右值为纯右值和将亡值 完美转发:利用引用折叠规则和forward保留参数原始类型特性 重点分析了移动构造/移动赋值的实现原理,以及右值引用在函数返回值和参数传递中的性能优化作用。通过示例代码展示了这些特性在实际开发中的应用场景和优势。

新人博主,欢迎大家互三、交流学习! 677

代数拓扑与AI架构:AI应用架构师深入探索数学研究如何分析复杂系统的结构特性

随着人工智能技术的飞速发展,AI系统变得越来越复杂。AI应用架构师需要有效的工具和方法来理解、设计和优化这些复杂系统。代数拓扑作为数学的一个分支,提供了独特的视角和技术来分析复杂系统的结构特性。本文旨在帮助AI应用架构师深入了解代数拓扑,以及如何将其应用于AI架构设计中,提升对复杂系统的分析能力。首先,我们会介绍代数拓扑和AI架构相关的核心概念及其联系,通过有趣的故事引入主题,让读者轻松理解复杂概念。接着,深入探讨代数拓扑的核心算法原理,结合具体的编程语言代码示例详细阐述。

大模型应用工坊 669

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

《C++进阶之C++11》【列表初始化 + 右值引用】

本文摘要: 文章介绍了C++11引入的列表初始化和右值引用两大特性。文中通过代码示例展示了列表初始化在数组、结构体和容器中的实际应用,并对比了C++98与C++11的初始化差异。这些特性显著提升了C++代码的简洁性和性能,是现代化C++编程的重要基础。

序属秋秋秋的博客 1728

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

【CPP11新特性,列表初始化】列表初始化与初始化列表是不是一个概念?列表是怎么初始化的?

CPP11列表初始化语法点介绍,列表初始化与初始化列表概念?列表是怎么初始化的简单介绍。

BinaryWiker的博客 1300

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

【C++杂货铺】C++11特性总结:列表初始化 | 声明 | STL的升级

本篇文章介绍了C++11中的三个新特性:列表初始化、声明、STL的升级

春人.的博客 6519

C++11 就地初始化与列表初始化

C++11之前,C++主要有以下几种初始化方式://小括号初始化 string str(&amp;amp;quot;hello&amp;amp;quot;);//等号初始化 string str=&amp;amp;quot;hello&amp;amp;quot;;//大括号初始化 struct Studnet{ char* name; int age; }; Studnet s={&amp;amp;quot;dablelv&amp

Doublelv 的博客专栏。 1万+

C++11列表初始化 {}

C++11引入的列表初始化{}提供了一种统一、安全的初始化方式,具有以下核心特性:1)统一语法,适用于基本类型、数组、结构体、类和容器;2)禁止窄化转换,防止数据精度丢失;3)支持通过std::initializer_list实现容器批量初始化。相较于传统初始化方式,列表初始化显著简化了代码,提高了安全性,特别是在容器初始化和类型转换方面表现突出。该特性使C++的初始化语法更加现代化和规范化。

TTKunn的博客 1649

【C++】——C++11新特性

C++,这门在系统开发、游戏开发、嵌入式等众多领域都占据主导地位的编程语言,一直在不断进化。C++11就像是C++家族中的一颗璀璨明星,闪耀着无数令人惊叹的新特性。如果你还在使用传统的C++编码方式,那你可能正在错过许多现代编程的便捷与高效。想象一下,用更少的代码编写出性能更高的程序,轻松应对复杂的并发场景,还能享受更加简洁和安全的内存管理。C++11就能让这一切成为现实。在这篇博文中,我会一点点揭开C++11新特性的神秘面纱,让你看到C++在这次重大更新之后所蕴含的无限潜力。

2402_85267481的博客 1874

【C++11】列表初始化

详细讲解C++11——列表初始化

tan_run的博客 1077

【C++11】:统一的列表初始化|声明|STL变化

对于c++11新特性的总结( ´◔︎ ‸◔︎`)

B1ue还在专注 1966

【C++】C++11新特性的讲解

C++11简介在2003年C++标准委员会曾经提交了一份技术勘误表简称TC1),使得C++03这个名字已经取代了C++98称为C++11之前的最新C++标准名称。不过由于C++03(TC1)主要是对C++98标准中的漏洞进行修复,语言的核心部分则没有改动,因此人们习惯性的把两个标准合并称为C++98/03标准。从C++0x到C++11C++标准10年磨一剑,第二个真正意义上的标准珊珊来迟。相比于C++98/03C++11。

Sxy_wspsby的博客 1242

【C++课程学习】:C++11(C++发展,列表初始化,声明auto,typeid,decltype)

(下面介绍来源于---文心一言)⛳️起源阶段:1979年,丹麦计算机科学家比雅尼·斯特劳斯特鲁普(Bjarne Stroustrup)发现C语言在表达能力、可维性和可展性方面的不足,开始对其进行了一系列的改进。斯特劳斯特鲁普在贝尔实验室开始从事将C改良为带类的C()的工作。他希望开发一个既要编程简单、正确可靠,又要运行高效、可移植的计算机程序设计语言。而以C语言为背景,以Simula思想为基础的语言,正好符合他的初衷和设想。

路虽远,行则将至!事虽难,做则必成! 4977
上一篇: C++进阶 —— multimap
下一篇: C++进阶 —— 范围for(C++11新特性)
挨代码
博客等级 码龄5年 1696粉丝 384原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值