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

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

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

一、何为列表初始化

C++中的列表初始化是一种用一对花括号 {} 来进行对象初始化的语法。它被引入主要是为了提供一种统一的初始化方式,适用于各种不同的数据类型和数据结构,包括基本类型、数组、结构体、类、STL 容器等。列表初始化在 C++11 标准中被引入,是现代 C++ 编程风格的一部分。MOn28资讯网——每日最新资讯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++ 中,窄转化是一种不安全的类型转换,因为它可能导致数据丢失或意外的行为。MOn28资讯网——每日最新资讯28at.com

以下是一些示例说明窄转化:MOn28资讯网——每日最新资讯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 引入的列表初始化中,提供了对缩窄转换的更严格的检查,不允许在列表初始化时发生缩窄转换,从而帮助程序员避免潜在的问题。MOn28资讯网——每日最新资讯28at.com

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

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

1. 不允许缩窄转换

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

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

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

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

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

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

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

4. 空列表初始化

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

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

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

当进行列表初始化时,编译器会根据构造函数的参数匹配规则选择相应的构造函数。MOn28资讯网——每日最新资讯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. 嵌套初始化

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

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

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

四、列表初始化的好处

列表初始化(Uniform Initialization)在 C++ 中引入的好处主要有以下几点:MOn28资讯网——每日最新资讯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++ 编程问题,它通常发生在类的对象声明上,导致程序员可能不是按照他们预期的方式初始化对象。这个问题的名字来源于这种情况的令人迷惑和难以理解。MOn28资讯网——每日最新资讯28at.com

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

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

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

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

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

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

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

什么是聚合类型

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

2、类型是一个类,且满足以下条件:MOn28资讯网——每日最新资讯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 的地方,可能需要考虑其他的初始化方式。MOn28资讯网——每日最新资讯28at.com

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

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

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

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

标签:
  • 热门焦点
  • 天猫精灵Sound Pro体验:智能音箱没有音质?来听听我的

    天猫精灵Sound Pro体验:智能音箱没有音质?来听听我的

    这几年除了手机作为智能生活终端最主要的核心之外,第二个可以成为中心点的产品是什么?——是智能音箱。 手机在执行命令的时候有两种操作方式,手和智能语音助手,而智能音箱只
  • 印度登月最关键一步!月船三号今晚进入环月轨道

    印度登月最关键一步!月船三号今晚进入环月轨道

    8月5日消息,据印度官方消息,月船三号将于北京时间今晚21时30分左右开始近月制动进入环月轨道。这是该探测器能够成功的最关键步骤之一,如果成功将开始围
  • 摸鱼心法第一章——和配置文件说拜拜

    摸鱼心法第一章——和配置文件说拜拜

    为了能摸鱼我们团队做了容器化,但是带来的问题是服务配置文件很麻烦,然后大家在群里进行了“亲切友好”的沟通图片图片图片图片对比就对比,简单对比下独立配置中心和k8s作为配
  • Golang 中的 io 包详解:组合接口

    Golang 中的 io 包详解:组合接口

    io.ReadWriter// ReadWriter is the interface that groups the basic Read and Write methods.type ReadWriter interface { Reader Writer}是对Reader和Writer接口的组合,
  • 量化指标是与非:挽救被量化指标扼杀的技术团队

    量化指标是与非:挽救被量化指标扼杀的技术团队

    作者 | 刘新翠整理 | 徐杰承本文整理自快狗打车技术总监刘新翠在WOT2023大会上的主题分享,更多精彩内容及现场PPT,请关注51CTO技术栈公众号,发消息【WOT2023PPT】即可直接领取
  • 如何使用JavaScript创建一只图像放大镜?

    如何使用JavaScript创建一只图像放大镜?

    译者 | 布加迪审校 | 重楼如果您曾经浏览过购物网站,可能遇到过图像放大功能。它可以让您放大图像的特定区域,以便浏览。结合这个小小的重要功能可以大大改善您网站的用户体验
  • 多线程开发带来的问题与解决方法

    多线程开发带来的问题与解决方法

    使用多线程主要会带来以下几个问题:(一)线程安全问题  线程安全问题指的是在某一线程从开始访问到结束访问某一数据期间,该数据被其他的线程所修改,那么对于当前线程而言,该线程
  • 19个 JavaScript 单行代码技巧,让你看起来像个专业人士

    19个 JavaScript 单行代码技巧,让你看起来像个专业人士

    今天这篇文章跟大家分享18个JS单行代码,你只需花几分钟时间,即可帮助您了解一些您可能不知道的 JS 知识,如果您已经知道了,就当作复习一下,古人云,温故而知新嘛。现在,我们就开始今
  • 慕岩炮轰抖音,百合网今何在?

    慕岩炮轰抖音,百合网今何在?

    来源:价值研究所 作者:Hernanderz&ldquo;难道就因为自己的一个产品牛逼了,从客服到总裁,都不愿意正视自己产品和运营上的问题,选择逃避了吗?&rdquo;这一番话,出自百合网联合创
Top