当前位置:首页 > 科技  > 软件

C++中列表初始化,你知多少?

来源: 责编: 时间:2024-03-18 09:43:01 321观看
导读一、何为列表初始化C++中的列表初始化是一种用一对花括号 {} 来进行对象初始化的语法。它被引入主要是为了提供一种统一的初始化方式,适用于各种不同的数据类型和数据结构,包括基本类型、数组、结构体、类、STL 容器等

一、何为列表初始化

C++中的列表初始化是一种用一对花括号 {} 来进行对象初始化的语法。它被引入主要是为了提供一种统一的初始化方式,适用于各种不同的数据类型和数据结构,包括基本类型、数组、结构体、类、STL 容器等。列表初始化在 C++11 标准中被引入,是现代 C++ 编程风格的一部分。WGe28资讯网——每日最新资讯28at.com

基本语法

Type variable = {value1, value2, ...};
  • 使用一对花括号 {} 来初始化对象。
  • 列表初始化对于类型转换更为严格,不允许缩窄转换(请看下面何为窄转化部分)。

示例

  • 基本类型:
int x = {42};double y = {3.14};
  • 数组:
int arr[] = {1, 2, 3, 4, 5};
  • 结构体:
struct Point {    int x;    int y;};Point p = {10, 20};
  • 类:
class MyClass {public:    int data;    double value;    MyClass(int d, double v) : data(d), value(v) {}};MyClass obj = {42, 3.14};
  • STL 容器:
#include <vector>#include <map>std::vector<int> vec = {1, 2, 3, 4, 5};std::map<int, std::string> myMap = {{1, "one"}, {2, "two"}};
  • 自定义类型:
class MyType {public:    int x;    double y;    MyType(int a, double b) : x(a), y(b) {}};MyType myVar = {5, 2.5};

二、何为窄转化

窄转化(Narrowing Conversion)指的是将一个具有较大范围的值转换为较小范围的类型时可能丢失信息的情况。这种转换可能导致截断或失真,因为目标类型的表示范围比源类型小。在 C++ 中,窄转化是一种不安全的类型转换,因为它可能导致数据丢失或意外的行为。WGe28资讯网——每日最新资讯28at.com

以下是一些示例说明窄转化:WGe28资讯网——每日最新资讯28at.com

  • 从浮点数到整数:
double myDouble = 3.14;int myInt = myDouble; // 窄转化,可能会截断小数部分
  • 从长整型到整数:
long long myLong = 1000000000000;int myInt = myLong; // 窄转化,可能会截断或溢出
  • 从大范围的整数类型到小范围的整数类型:
long long myLong = 1000000000000;int myInt = static_cast<int>(myLong); // 窄转化,可能会截断或溢出

窄转化是需要小心处理的,因为它可能导致数据的损失和不确定的行为。在需要进行类型转换时,最好使用安全的转换方式,例如使用 static_cast 并在可能丢失信息的地方进行显式的检查和处理。在 C++11 引入的列表初始化中,提供了对缩窄转换的更严格的检查,不允许在列表初始化时发生缩窄转换,从而帮助程序员避免潜在的问题。WGe28资讯网——每日最新资讯28at.com

三、列表初始化规则和特点

列表初始化有一些规则和特点,主要包括以下几个方面:WGe28资讯网——每日最新资讯28at.com

1. 不允许缩窄转换

列表初始化对类型转换更为严格,不允许发生缩窄转换,即不允许将一个精度更高的类型赋值给一个精度较低的类型。WGe28资讯网——每日最新资讯28at.com

int x = {3.14}; // 错误,尝试缩窄转换

2. 对于数组,列表初始化的大小由元素个数决定

int arr[] = {1, 2, 3}; // 合法,数组大小为3

3. 类型不匹配时可能调用构造函数

当列表初始化的类型和目标类型不匹配时,如果存在适当的构造函数,编译器会尝试调用构造函数进行初始化。WGe28资讯网——每日最新资讯28at.com

class MyClass {public:    int data;    double value;    MyClass(int d, double v) : data(d), value(v) {}};MyClass obj = {42, 3.14}; // 合法,调用构造函数

4. 空列表初始化

在某些情况下,可以使用空的花括号 {} 进行初始化,这会被解释为对应类型的默认值。WGe28资讯网——每日最新资讯28at.com

int x = {}; // x 被初始化为 0double y = {}; // y 被初始化为 0.0

5. 对于类类型,构造函数的匹配规则

当进行列表初始化时,编译器会根据构造函数的参数匹配规则选择相应的构造函数。WGe28资讯网——每日最新资讯28at.com

class Example {public:    Example(int a, double b);    Example(std::string str);};Example obj1 = {42, 3.14};  // 调用构造函数 Example(int, double)Example obj2 = {"Hello"};    // 调用构造函数 Example(std::string)

6. 嵌套初始化

可以使用嵌套的列表初始化来初始化嵌套的数据结构。WGe28资讯网——每日最新资讯28at.com

std::vector<std::vector<int>> matrix = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};

总体来说,列表初始化提供了一种简洁且直观的初始化语法,同时对类型匹配和转换有着更为严格的规定,减少了一些初始化时可能发生的错误。WGe28资讯网——每日最新资讯28at.com

四、列表初始化的好处

列表初始化(Uniform Initialization)在 C++ 中引入的好处主要有以下几点:WGe28资讯网——每日最新资讯28at.com

  • 一致性:列表初始化提供了一种一致的初始化语法,可以用于初始化各种类型的对象,包括基本类型、数组、结构体、类、STL 容器等。这种一致性使得代码更加清晰和易读。
int x = {42};             // 初始化基本类型int arr[] = {1, 2, 3};    // 初始化数组Point p = {10, 20};       // 初始化结构体MyClass obj = {42, 3.14};  // 初始化类std::vector<int> vec = {1, 2, 3}; // 初始化容器
  • 防止窄化转换:列表初始化对类型转换更为严格,不允许发生缩窄转换,从而减少了一些可能引入 bug 的情况。
int x = {3.14}; // 错误,尝试缩窄转换
  • 构造函数匹配:当进行列表初始化时,如果存在适当的构造函数,编译器会尝试调用构造函数进行初始化。这提高了代码的灵活性,使得用户定义的类型更容易进行初始化。
class MyClass {public:    int data;    double value;    MyClass(int d, double v) : data(d), value(v) {}};MyClass obj = {42, 3.14}; // 调用构造函数
  • 简洁性:列表初始化的语法相对简洁,通过一对花括号{}就可以完成初始化,避免了传统的各种初始化方式可能导致的歧义。
int arr[] = {1, 2, 3};  // 合法,简洁
  • 避免 most vexing parse: 传统的初始化语法在某些情况下可能会导致 most vexing parse,而列表初始化语法避免了这一问题。

"Most Vexing Parse" 是一个有趣而令人困扰的 C++ 编程问题,它通常发生在类的对象声明上,导致程序员可能不是按照他们预期的方式初始化对象。这个问题的名字来源于这种情况的令人迷惑和难以理解。WGe28资讯网——每日最新资讯28at.com

Most Vexing Parse 主要发生在下面这样的情况:WGe28资讯网——每日最新资讯28at.com

class MyClass {public:    MyClass() {}};int main() {    MyClass obj();  // 最令人迷惑的解析,声明了一个函数而不是对象    // ...    return 0;}

在上述代码中,MyClass obj(); 被编译器解释为声明一个返回 MyClass 类型的函数而不是创建一个 MyClass 类型的对象。这是因为在 C++ 中,如果声明一个函数的时候带有空括号,编译器会将其解释为一个函数声明而不是一个对象定义。WGe28资讯网——每日最新资讯28at.com

为了避免 most vexing parse,可以使用以下两种方式之一:WGe28资讯网——每日最新资讯28at.com

  • 使用花括号初始化:
MyClass obj{};  // 使用花括号初始化,避免 most vexing parse
  • 使用括号初始化:
MyClass obj();  // 编译器会将其解释为函数声明MyClass obj{};  // 使用括号初始化,避免 most vexing parse

这个问题是由 C++ 语法规则引起的,对于初学者来说可能会令人困扰。因此,在声明和初始化对象时,特别是在有可能发生 most vexing parse 的地方,建议使用花括号初始化或括号初始化,以避免潜在的问题。WGe28资讯网——每日最新资讯28at.com

五、不适用列表初始化的情况

什么是聚合类型

1、类型是一个普通数组,如int[5],char[],double[]等 WGe28资讯网——每日最新资讯28at.com

2、类型是一个类,且满足以下条件:WGe28资讯网——每日最新资讯28at.com

  • 没有用户声明的构造函数
  • 没有用户提供的构造函数(允许显示预置或弃置的构造函数)
  • 没有私有或保护的非静态数据成员
  • 没有基类
  • 没有虚函数
  • 没有{}和=直接初始化的非静态数据成员
  • 没有默认成员初始化器

虽然列表初始化是一种很方便和清晰的初始化方式,但有一些情况下不适合或者不能使用列表初始化:

  • 不支持聚合初始化的类列表初始化主要用于聚合类型的初始化,而对于不支持聚合初始化的类,不能使用列表初始化。一个类如果有用户自定义的构造函数、私有/受保护的非静态数据成员,或者基类没有默认构造函数,那么该类就不再是聚合类型。
class NotAggregate {public:    int x;    int y;    NotAggregate(int a, int b) : x(a), y(b) {}};NotAggregate obj = {1, 2}; // 错误,NotAggregate 不是聚合类型
  • 不能进行窄化转换的地方:列表初始化不允许发生窄化转换,因此在需要执行窄化转换的地方不能使用列表初始化。
double myDouble = 3.14;int myInt = myDouble; // 合法,但列表初始化会报错
  • 需要避免 most vexing parse 的地方:在可能发生 most vexing parse(最令人迷惑的解析)的地方,列表初始化可能不适用。这通常发生在类的默认构造函数被误解为函数声明的情况下。
class MyClass {public:    MyClass() {}};MyClass obj();   // 最令人迷惑的解析,声明了一个函数而不是对象MyClass obj{};   // 正确的初始化方式

总之,虽然列表初始化是一种很便捷和安全的初始化方式,但在某些情况下,特别是对于非聚合类型和可能导致 most vexing parse 的地方,可能需要考虑其他的初始化方式。WGe28资讯网——每日最新资讯28at.com

本文链接:http://www.28at.com/showinfo-26-76573-0.htmlC++中列表初始化,你知多少?

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com

上一篇: 怎样设计全链路压力测试平台?

下一篇: Vue3 中的 Suspense:异步组件加载与占位符管理

标签:
  • 热门焦点
  • 小米降噪蓝牙耳机Necklace分享:听一首歌 读懂一个故事

    在今天下午的小米Civi 2新品发布会上,小米还带来了一款新的降噪蓝牙耳机Necklace,我们也在发布结束的第一时间给大家带来这款耳机的简单分享。现在大家能见到最多的蓝牙耳机
  • 十个可以手动编写的 JavaScript 数组 API

    JavaScript 中有很多API,使用得当,会很方便,省力不少。 你知道它的原理吗? 今天这篇文章,我们将对它们进行一次小总结。现在开始吧。1.forEach()forEach()用于遍历数组接收一参
  • Rust中的高吞吐量流处理

    作者 | Noz编译 | 王瑞平本篇文章主要介绍了Rust中流处理的概念、方法和优化。作者不仅介绍了流处理的基本概念以及Rust中常用的流处理库,还使用这些库实现了一个流处理程序
  • 一篇文章带你了解 CSS 属性选择器

    属性选择器对带有指定属性的 HTML 元素设置样式。可以为拥有指定属性的 HTML 元素设置样式,而不仅限于 class 和 id 属性。一、了解属性选择器CSS属性选择器提供了一种简单而
  • 腾讯VS网易,最卷游戏暑期档,谁能笑到最后?

    作者:无锈钵来源:财经无忌7月16日晚,上海1862时尚艺术中心。伴随着幻象的精准命中,硕大的荧幕之上,比分被定格在了14:12,被寄予厚望的EDG战队以绝对的优势战胜了BLG战队,拿下了总决
  • 阿里瓴羊One推出背后,零售企业迎数字化新解

    作者:刘旷近年来随着数字经济的高速发展,各式各样的SaaS应用服务更是层出不穷,但本质上SaaS大多局限于单一业务流层面,对用户核心关切的增长问题等则没有提供更好的解法。在Saa
  • 2纳米决战2025

    集微网报道 从三强争霸到四雄逐鹿,2nm的厮杀声已然隐约传来。无论是老牌劲旅台积电、三星,还是誓言重回先进制程领先地位的英特尔,甚至初成立不久的新
  • 由于成本持续增加,笔记本产品价格预计将明显上涨

    根据知情人士透露,由于材料、物流等成本持续增加,笔记本产品价格预计将在2021年下半年有明显上涨。进入6月下旬以来,全球半导体芯片缺货情况加剧,显卡、处理器
  • 三翼鸟智能家居亮相电博会,让用户体验更真实

    2021电博会在青岛国际会展中心开幕中,三翼鸟直接把“家”搬到了现场,成为了展会的一大看点。这也是三翼鸟继9月9日发布了行业首个一站式定制智慧家平台后的
Top