C++11 列表初始化与类型声明
目录
0.前言
1.C++11介绍
2.统一的列表初始化
2.1{}初始化
2.2initializer_list
2.2.1initializer_list 的基本用法
2.2.2用于类的 initializer_list 构造函数
2.2.3与标准库容器的结合
2.2.4优势与注意事项
3.新声明
3.1auto
3.1.1基本用法
3.1.2优势
3.1.3注意事项
3.2decltype
3.2.1基本用法
3.2.2与 auto 的区别
3.2.3用于返回类型推导
3.3nullptr
3.3.1基本用法
3.3.2与 NULL 的区别
3.3.3优势
4.小结
(图源网络,侵删)
0.前言
在现代软件开发中,数据结构和编程语言的特性直接影响代码的效率和可维护性。尽管 C++98 提供了丰富的数据结构和功能,但在代码简洁性和类型安全性方面仍有不足。C++11 引入了许多新特性,如右值引用、lambda 表达式、智能指针和多线程库等,极大地增强了语言的现代化和功能性。本文将重点介绍 C++11 的列表初始化和类型声明新特性,通过实例展示它们的用法和优势,帮助开发者更好地理解和应用这些特性。
1.C++11介绍
C++11,也被称为 C++0x,是 C++ 标准的一次重要更新,于 2011 年正式发布。它的出现标志着 C++ 语言的一个重大转折点,旨在解决 C++98 中的各种局限性和问题,使 C++ 更加现代化和高效。C++11 的开发始于 2005 年,其目标是提升语言的性能和可用性,同时保持与现有代码的兼容性。标准委员会通过广泛的讨论和实验,引入了大量的新特性,包括右值引用(Rvalue References)、lambda 表达式、智能指针、多线程库、以及更为简洁和安全的初始化和类型声明方式。C++11 不仅极大地丰富了语言本身的功能,也为开发者提供了更为强大的工具,帮助他们编写更高效、更可靠的代码。
2.统一的列表初始化
C++11 引入了统一的列表初始化语法,使得对象的初始化方式更加一致和简洁。新的列表初始化方式通过使用花括号 {} 来统一不同类型对象的初始化过程,从而简化代码,减少错误。
2.1{}初始化
在 C++11 之前,初始化对象的方式因对象类型的不同而各异。对于基本类型、数组、结构体、类等,各自有不同的初始化语法。这种多样化的初始化方式不仅让代码显得杂乱无章,还容易引发各种隐式转换错误和未定义行为。C++11 的 {} 初始化通过提供一种统一的语法,解决了这些问题。
基本类型的初始化
在 C++11 中,花括号 {} 可以用于初始化基本类型:
int a{10}; // 直接初始化
int b = {20}; // 复制初始化
int c{}; // 值初始化,c 被初始化为 0
这种初始化方式的一个显著优点是,它能够防止窄化转换(narrowing conversion):
int x{3.14}; // 错误:不能将 double 赋值给 int
int y = 3.14; // 有效,但 y 被截断为 3
通过使用 {} 初始化,编译器会检测并阻止潜在的错误转换,增强了代码的安全性。
类和结构体的初始化
C++11 的 {} 初始化同样适用于类和结构体对象:
struct Point {int x;int y;
};Point p1{1, 2}; // 直接初始化
Point p2 = {3, 4}; // 复制初始化
对于类对象,C++11 允许通过 {} 初始化来调用构造函数:
class MyClass {
public:MyClass(int a, int b) : x(a), y(b) {}
private:int x, y;
};MyClass obj{10, 20}; // 调用 MyClass 的构造函数
数组和容器的初始化
C++11 使得数组和标准库容器的初始化更加简洁和直观:
int arr[] = {1, 2, 3, 4, 5}; // 数组初始化
std::vector<int> vec{1, 2, 3, 4, 5}; // std::vector 初始化
std::map<int, std::string> m = {{1, "one"},{2, "two"},{3, "three"}
}; // std::map 初始化
这种统一的列表初始化方式不仅简化了代码,还增强了代码的可读性和一致性,使开发者能够更轻松地管理复杂的数据结构。
2.2initializer_list
C++11 引入了 initializer_list 类型,以支持更加灵活和统一的列表初始化。initializer_list 是标准库中的一个模板类,允许构造函数和其他函数接收一个初始化列表,从而简化了容器和对象的初始化过程。
2.2.1initializer_list 的基本用法
initializer_list 提供了一种方式,使得函数可以接收一组由花括号 {} 包裹的初始值。以下是一个简单的示例:
#include <initializer_list>
#include <iostream>void printList(std::initializer_list<int> list) {for (auto elem : list) {std::cout << elem << " ";}std::cout << std::endl;
}int main() {printList({1, 2, 3, 4, 5});return 0;
}
在这个例子中,函数 printList 接受一个 initializer_list<int> 类型的参数,并通过范围循环(range-based for loop)来遍历并打印列表中的元素。
2.2.2用于类的 initializer_list 构造函数
initializer_list 常用于定义容器类的构造函数,使得容器类可以接受初始化列表,从而简化对象的初始化。例如:
#include <initializer_list>
#include <vector>
#include <iostream>class MyContainer {
public:MyContainer(std::initializer_list<int> list) {for (auto elem : list) {data.push_back(elem);}}void print() const {for (auto elem : data) {std::cout << elem << " ";}std::cout << std::endl;}private:std::vector<int> data;
};int main() {MyContainer container = {1, 2, 3, 4, 5};container.print();return 0;
}
在这个例子中,MyContainer 类的构造函数接受一个 initializer_list<int> 类型的参数,并使用该列表初始化 data 成员。这样,用户可以直接使用花括号语法来初始化 MyContainer 对象。
2.2.3与标准库容器的结合
initializer_list 在标准库容器中得到了广泛应用。例如,std::vector、std::set 和 std::map 等容器都支持通过 initializer_list 进行初始化:
#include <vector>
#include <set>
#include <map>
#include <iostream>int main() {std::vector<int> vec = {1, 2, 3, 4, 5};std::set<std::string> strSet = {"one", "two", "three"};std::map<int, std::string> intToStrMap = {{1, "one"},{2, "two"},{3, "three"}};for (int num : vec) {std::cout << num << " ";}std::cout << std::endl;for (const auto& str : strSet) {std::cout << str << " ";}std::cout << std::endl;for (const auto& pair : intToStrMap) {std::cout << pair.first << ": " << pair.second << " ";}std::cout << std::endl;return 0;
}
输出结果:
1 2 3 4 5
one three two
1: one 2: two 3: three
在这个示例中,std::vector、std::set 和 std::map 都通过 initializer_list 进行了初始化,使得代码更加简洁和易读。
2.2.4优势与注意事项
使用 initializer_list 具有以下几个优势:
- 简洁性:通过花括号
{}初始化列表,使得代码更加简洁和直观。 - 一致性:提供了一种统一的初始化语法,适用于各种类型的对象。
- 安全性:避免了某些类型转换问题,提高了代码的安全性。
然而,使用 initializer_list 时也需注意以下几点:
- 不可修改:
initializer_list本身是不可修改的,不能添加或删除元素。 - 生命周期:
initializer_list的元素是对外部数组的引用,使用时需要确保数组的生命周期长于initializer_list。
3.新声明
C++11 引入了几种新的类型声明方式,使得代码更加简洁和易于维护。新的类型声明方式包括 auto、decltype 和 nullptr,它们极大地增强了 C++ 语言的类型推导能力和代码安全性。
3.1auto
auto 关键字允许编译器根据初始化表达式自动推导变量的类型,从而简化了变量声明,特别是在复杂类型的声明中。
3.1.1基本用法
auto 可以用于推导任何类型的变量,包括基本类型、指针、引用、容器迭代器等:
int x = 10;
auto a = x; // a 被推导为 int 类型double y = 5.5;
auto b = y; // b 被推导为 double 类型auto c = &x; // c 被推导为 int* 类型std::vector<int> vec = {1, 2, 3};
auto it = vec.begin(); // it 被推导为 std::vector<int>::iterator 类型
3.1.2优势
使用 auto 的优势包括:
- 简化代码:减少冗长的类型声明,特别是在使用 STL 容器和迭代器时。
- 提高可读性:让代码更简洁,更易读。
- 减少错误:降低手动写错类型的风险,特别是在类型复杂或容易变化时。
3.1.3注意事项
尽管 auto 带来了诸多便利,但在使用时需要注意以下几点:
-
明确性:在某些情况下,
auto可能会降低代码的明确性和可读性,需要开发者对推导出的类型有清晰的认识。 -
推导规则:
auto会根据右值表达式推导类型,有时可能会与预期不符。例如,数组类型会被推导为指针类型:int arr[3] = {1, 2, 3}; auto p = arr; // p 被推导为 int*
3.2decltype
decltype 关键字用于查询表达式的类型,并返回该类型。它在泛型编程和模板编程中尤为有用,可以精确地推导出变量或表达式的类型。
3.2.1基本用法
decltype 主要用于变量声明、函数返回类型推导等:
int x = 10;
decltype(x) y = 20; // y 的类型与 x 相同,都是 intconst int& z = x;
decltype(z) w = x; // w 的类型与 z 相同,都是 const int&
3.2.2与 auto 的区别
auto 是根据初始化表达式推导类型,而 decltype 则是根据表达式的类型进行推导。以下是一个对比示例:
int x = 10;
auto a = x; // a 是 int
decltype(x) b = x; // b 是 intconst int& y = x;
auto c = y; // c 是 int,丢弃了 const 和引用
decltype(y) d = y; // d 是 const int&
3.2.3用于返回类型推导
在模板编程中,decltype 常用于推导函数的返回类型:
template <typename T1, typename T2>
auto add(T1 a, T2 b) -> decltype(a + b) {return a + b;
}
3.3nullptr
C++11 引入了 nullptr 关键字,用于表示空指针,替代了传统的 NULL 宏。nullptr 是一个类型安全的空指针字面值,避免了 NULL 可能引发的类型转换问题。
3.3.1基本用法
nullptr 可以与任意指针类型兼容:
int* p1 = nullptr; // int* 类型的空指针
double* p2 = nullptr; // double* 类型的空指针void func(int* ptr) {if (ptr == nullptr) {std::cout << "Pointer is null" << std::endl;}
}int main() {func(nullptr); // 安全地传递空指针return 0;
}
3.3.2与 NULL 的区别
NULL 宏通常定义为 0 或 (void*)0,在某些情况下可能引发类型不匹配的问题:
void f(int);
void f(void*);f(0); // 调用 f(int)
f(NULL); // 调用 f(int),可能意图是 f(void*)
f(nullptr); // 调用 f(void*),避免了歧义
3.3.3优势
使用 nullptr 的优势包括:
- 类型安全:避免了
NULL引发的类型转换问题。 - 代码清晰:显式表示指针为空,使代码更具可读性。
4.小结
C++11 引入的列表初始化和新的类型声明方式,使得 C++ 语言更加强大和易用。花括号 {} 初始化和 initializer_list 提供了统一的初始化方式,简化了对象的创建过程;而 auto、decltype 和 nullptr 则增强了类型推导能力,减少了代码中的冗余和错误。掌握这些新特性,可以显著提高 C++ 编程的效率和代码质量。
相关文章:
C++11 列表初始化与类型声明
目录 0.前言 1.C11介绍 2.统一的列表初始化 2.1{}初始化 2.2initializer_list 2.2.1initializer_list 的基本用法 2.2.2用于类的 initializer_list 构造函数 2.2.3与标准库容器的结合 2.2.4优势与注意事项 3.新声明 3.1auto 3.1.1基本用法 3.1.2优势 3.1.3注意事项 3.2declt…...
缓存策略自定义:Laravel应用性能优化秘籍
缓存策略自定义:Laravel应用性能优化秘籍 在现代Web应用中,缓存是一种提高应用性能和响应速度的有效手段。Laravel框架提供了强大的缓存机制,支持多种缓存驱动,如文件、数据库、Redis等。然而,在某些情况下࿰…...
python连接sqlserver,封装操作
1封装 # 导入Flask类 import pymssql import tracebackclass Mssql(object):# 连接库def base(database):connect pymssql.connect(usersa,password123456,databasef{database},charsetutf8,as_dictTrue)if connect:print("数据库连接成功!")else:print…...
原生PHP/JS自主开发的交友内核框架婚恋交友系统V10
本文来自:婚恋交友系统V10 - 源码1688 应用介绍 原生PHP/JS自主开发的交友内核框架,极高性能、无捆绑、自主权、无流水扣点、独立全开源 01脱单盲盒:脱单盲盒类似于漂流瓶,先将自己《投放》到盲盒中,另一伴有缘将您取…...
如何在Java、Python、GO程序中使用AI人脸识别API接口
AI人脸识别是一种通过面部识别或确认一个人身份的软件。它通过识别和测量图像中的面部特征来工作。面部识别可以识别图像或视频中的人脸,确定两幅图像中的人脸是否属于同一个人,或者在大量现有图像中搜索人脸。 AI人脸识别的优势是什么? 高…...
在vue使用MQTT
在vue中使用MQTT 最近有个需求,需要前端直接链接mqtt,想到后面可能多出使用,就封装成了hooks 中间遇到了一个坑,就是浏览器默认不支持mqtt协议,其借助了webSocket实现的mqtt协议, 而mqtt默认未开启webSocke…...
DNS、网关、IP、DHCP
DNS、网关、IP、DHCP:深入剖析与理解 在计算机网络的世界中,DNS、网关、IP和DHCP是四个至关重要的概念,它们共同构建了互联网的基础架构,确保了数据的准确传输和设备的有效连接。本文将深入剖析这四个概念,帮助读者更…...
vue2 vue3 props 的处理机制
在 Vue 2 中,props 是单向数据流,父组件向子组件传递的 props 默认情况下是不具有响应式特性的。这意味着当父组件的数据发生变化时,如果传递给子组件的 props 发生变化,子组件不会自动更新视图。 具体来说,在 Vue 2 …...
C++第十弹 ---- vector的介绍及使用
目录 前言vector的介绍及使用1. vector的使用1.1 vector的定义1.2 iterator的使用1.3 vector空间增长问题1.4 vector增删查改 2. vector迭代器失效问题(重点) 总结 前言 本文介绍了C中的vector数据结构及其使用方法。 更多好文, 持续关注 ~ 酷酷学!!! 正文开始 vector的介绍…...
ValueError: invalid literal for int() with base 10: ‘a‘
ValueError: invalid literal for int() with base 10: ‘a‘ 目录 ValueError: invalid literal for int() with base 10: ‘a‘ 【常见模块错误】 【解决方案】 欢迎来到英杰社区https://bbs.csdn.net/topics/617804998 欢迎来到我的主页,我是博主英杰ÿ…...
[C++探索]初始化列表,static成员,友元函数,内部类,匿名对象
💖💖💖欢迎来到我的博客,我是anmory💖💖💖 又和大家见面了 欢迎来到C探索系列 作为一个程序员你不能不掌握的知识 先来自我推荐一波 个人网站欢迎访问以及捐款 推荐阅读 如何低成本搭建个人网站…...
搭建自己的金融数据源和量化分析平台(二):读取上交所股票列表
我在上交所没发现上交所有像深交所一样的一键下载股票xls文档的按钮,因此上交所的股票列表读取就会比较麻烦。总体思路是查出来所有股票的代码之后根据股票代码逐一发起HTTP请求读取公司英文名、总股本、流通股本等详细信息,这就导致上交所爬虫的网络交互…...
Kafka知识总结(分区机制+压缩机制+拦截器+副本机制)
文章收录在网站:http://hardyfish.top/ 文章收录在网站:http://hardyfish.top/ 文章收录在网站:http://hardyfish.top/ 文章收录在网站:http://hardyfish.top/ 分区机制 分区策略 分区策略是决定生产者将消息发送到哪个分区的…...
WordPress原创插件:搜索引擎抓取首图seo图片
WordPress原创插件:搜索引擎抓取首图seo图片 插件设置 插件将在网站头部添加适当的meta标签,以便百度等搜索引擎抓取指定的固定图像。 插件下载 https://download.csdn.net/download/huayula/89596527...
Android Framework 之AMS
它管理了系统的四大组件:Activity、Service、ContentProvider、Broadcast。 它除了管理四大组件外,同时也负责管理和调度所有的进程 AMS相关目录结构 AMS代码主要在下面几个目录(AndroidQ上AMS相关部分功能移到了wm下): frameworks/base/core/java/andro…...
AnConda环境配置学习笔记
AnConda环境配置 个人笔记,自己学习使用。 1、软件安装 去官网或者是清华大学镜像下载 2、环境配置 Conda 查看版本:conda --version 更新所有库 conda update --all(千万不要跟新,版本不匹配) matploitlib安装cond…...
架构师的36项修炼 学习笔记
架构师的36项修炼 学习笔记 分布式缓存 缓存特点 1.技术简单 2.性能提升明显 3.应用场景多 缓存数据存储 hash表 缓存的关键指标 命中率 缓存失效方式 超时失效 LLT 实时清除 代理缓存 反向代理缓存 多层反向代理缓存 内容分发网络CDN 通读缓存 包括代理缓存…...
Python | “IndexError: tuple index out of range” 【已解决】
Python | “IndexError: tuple index out of range” 【已解决】 IndexError: tuple index out of range 深度解析与实战指南 在Python编程中,IndexError: tuple index out of range是一个常见的错误,它发生在尝试访问元组(或其他可索引的数…...
Linux上部署easySpider及基本使用
一、安装及简介 默认使用Chrome浏览器。 1、下载压缩包 官网:易采集EasySpider:无代码可视化爬虫/浏览器自动化测试软件 Linux版只适用于Ubuntu 20.04及以上版本、Deepin、Debian及其衍生版本。 (建议使用)下载网址/Github下…...
Qt Designer,仿作一个ui界面的练习(二):部件内容的填充
有了完成了布局的基本框架设计之后,对各个部件逐步完成内容的填充。 一、还是从顶边栏开始: 1、在顶边栏的topLogo里面拖入一个QLabel(标签),命名为logoImage,删除标签的文字。 2、右键点击topLogo&#x…...
OpenLayers 可视化之热力图
注:当前使用的是 ol 5.3.0 版本,天地图使用的key请到天地图官网申请,并替换为自己的key 热力图(Heatmap)又叫热点图,是一种通过特殊高亮显示事物密度分布、变化趋势的数据可视化技术。采用颜色的深浅来显示…...
相机从app启动流程
一、流程框架图 二、具体流程分析 1、得到cameralist和对应的静态信息 目录如下: 重点代码分析: 启动相机前,先要通过getCameraIdList获取camera的个数以及id,然后可以通过getCameraCharacteristics获取对应id camera的capabilities(静态信息)进行一些openCamera前的…...
IoT/HCIP实验-3/LiteOS操作系统内核实验(任务、内存、信号量、CMSIS..)
文章目录 概述HelloWorld 工程C/C配置编译器主配置Makefile脚本烧录器主配置运行结果程序调用栈 任务管理实验实验结果osal 系统适配层osal_task_create 其他实验实验源码内存管理实验互斥锁实验信号量实验 CMISIS接口实验还是得JlINKCMSIS 简介LiteOS->CMSIS任务间消息交互…...
根据万维钢·精英日课6的内容,使用AI(2025)可以参考以下方法:
根据万维钢精英日课6的内容,使用AI(2025)可以参考以下方法: 四个洞见 模型已经比人聪明:以ChatGPT o3为代表的AI非常强大,能运用高级理论解释道理、引用最新学术论文,生成对顶尖科学家都有用的…...
基于Java Swing的电子通讯录设计与实现:附系统托盘功能代码详解
JAVASQL电子通讯录带系统托盘 一、系统概述 本电子通讯录系统采用Java Swing开发桌面应用,结合SQLite数据库实现联系人管理功能,并集成系统托盘功能提升用户体验。系统支持联系人的增删改查、分组管理、搜索过滤等功能,同时可以最小化到系统…...
浪潮交换机配置track检测实现高速公路收费网络主备切换NQA
浪潮交换机track配置 项目背景高速网络拓扑网络情况分析通信线路收费网络路由 收费汇聚交换机相应配置收费汇聚track配置 项目背景 在实施省内一条高速公路时遇到的需求,本次涉及的主要是收费汇聚交换机的配置,浪潮网络设备在高速项目很少,通…...
Leetcode33( 搜索旋转排序数组)
题目表述 整数数组 nums 按升序排列,数组中的值 互不相同 。 在传递给函数之前,nums 在预先未知的某个下标 k(0 < k < nums.length)上进行了 旋转,使数组变为 [nums[k], nums[k1], …, nums[n-1], nums[0], nu…...
DAY 45 超大力王爱学Python
来自超大力王的友情提示:在用tensordoard的时候一定一定要用绝对位置,例如:tensorboard --logdir"D:\代码\archive (1)\runs\cifar10_mlp_experiment_2" 不然读取不了数据 知识点回顾: tensorboard的发展历史和原理tens…...
结构化文件管理实战:实现目录自动创建与归类
手动操作容易因疲劳或疏忽导致命名错误、路径混乱等问题,进而引发后续程序异常。使用工具进行标准化操作,能有效降低出错概率。 需要快速整理大量文件的技术用户而言,这款工具提供了一种轻便高效的解决方案。程序体积仅有 156KB,…...
MeshGPT 笔记
[2311.15475] MeshGPT: Generating Triangle Meshes with Decoder-Only Transformers https://library.scholarcy.com/try 真正意义上的AI生成三维模型MESHGPT来袭!_哔哩哔哩_bilibili GitHub - lucidrains/meshgpt-pytorch: Implementation of MeshGPT, SOTA Me…...
