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

C++11 使用 {} 进行初始化

文章目录

  • C++11 使用 {} 进行初始化
    • 1 列表初始化的基本概念
    • 2 列表初始化的用法
      • 2.1 基本数据类型
      • 2.2 数组
      • 2.3 类和结构体
      • 2.4 容器初始化
    • 3 列表初始化的优势
    • 4 注意事项
    • 5 示例代码
    • 6 总结

C++11 使用 {} 进行初始化

1 列表初始化的基本概念

在 C++11 及之后的版本中,使用大括号 {} 进行初始化得到了显著增强,并且被赋予了新的名称:列表初始化(list initialization)或统一初始化(uniform initialization)。这种初始化方式提供了更高的类型安全性和更清晰的语法,特别是在避免某些类型的构造函数歧义方面。

2 列表初始化的用法

以下是一些在 C++11 中使用 {} 进行初始化的关键点和示例:

2.1 基本数据类型

对于基本数据类型(如 int, double, char 等),你可以使用 {} 进行初始化,但通常这不是必需的,因为直接使用 = 也可以达到相同的效果。然而,{} 可以在某些情况下避免潜在的窄化转换警告或错误。

int a{10};         // 整数初始化
double b{3.14};    // 浮点数初始化
char c{'A'};       // 字符初始化
bool d{true};      // 布尔值初始化

当使用空的 {} 语法进行初始化时,编译器会自动将剩余的部分初始化为 0 或空值,这有助于避免未初始化变量的问题。

struct Sample {int a{};        // 初始化为 0double b{};     // 初始化化为 0.0
};

2.2 数组

对于数组,{} 是初始化数组元素的常用方式。

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

2.3 类和结构体

对于类和结构体,如果它们没有定义构造函数或者定义了接受 std::initializer_list 的构造函数,你可以使用 {} 进行初始化。

  • 没有定义构造函数:这种情况下,类被视为聚合类型,可以直接使用 {} 初始化其成员。
struct Point {int x{};int y{};
};Point p = {1, 2}; // 初始化结构体
  • 定义了接受 std::initializer_list 的构造函数:如果类定义了一个接受 std::initializer_list 的构造函数,那么使用 {} 会调用这个构造函数。
class MyClass {
public:MyClass(std::initializer_list<int> list) {// 处理 list}
};MyClass obj = {1, 2, 3, 4}; // 调用接受 std::initializer_list 的构造函数

2.4 容器初始化

C++11 中的标准容器(如std::vectorstd::list等)也支持列表初始化。这使得容器可以像数组一样被初始化。例如:

std::vector<int> vec{1, 2, 3, 4, 5}; // 初始化整数向量vec

3 列表初始化的优势

  1. 防止窄化转换

    窄化转换是指在类型转换时可能导致信息的损失或不准确的转换。列表初始化在初始化过程中会禁止窄化转换,从而提高了代码的类型安全性。例如:

    int x{3.14}; // 编译错误:禁止从double到int的窄化转换
    
  2. 提高代码可读性

    列表初始化使用统一的语法{}进行初始化,这使得代码更加简洁和一致。同时,它也避免了使用不同初始化方式时可能产生的混淆和错误。

  3. 支持聚合体初始化

    在 C++11 中,聚合体的概念被扩展,它可以通过初始化列表进行初始化。这意味着符合聚合体条件的类型可以使用更灵活的初始化方式。例如:

    struct Rectangle {int width{};int height{};
    };Rectangle rect{10, 20}; // 使用聚合体初始化变量rect
    

4 注意事项

  • 避免构造函数歧义:在某些情况下,使用 {} 可以避免由于多个构造函数导致的歧义。
  • 窄化转换:对于可能导致数据丢失的窄化转换,使用 {} 可能会引发编译错误,从而提供更高的类型安全性。
  • 默认构造函数:如果类没有定义默认构造函数且你尝试使用 {} 初始化其对象,而该类又不是聚合类型且没有接受 std::initializer_list 的构造函数,那么这将导致编译错误。

5 示例代码

#include <iostream>
#include <vector>
#include <initializer_list>struct Point {int x, y;
};class MyClass {
public:MyClass(int a, int b) : a_(a), b_(b) {}MyClass(std::initializer_list<int> list) {// 假设我们只关心列表的第一个元素a_ = list.begin() != list.end() ? *list.begin() : 0;b_ = 0; // 其他元素被忽略}void print() const {std::cout << "a_ = " << a_ << ", b_ = " << b_ << std::endl;}
private:int a_, b_;
};int main() {Point p = {1, 2}; // 初始化结构体MyClass obj1(3, 4); // 使用构造函数初始化MyClass obj2 = {5}; // 使用接受 std::initializer_list 的构造函数初始化obj1.print(); // 输出: a_ = 3, b_ = 4obj2.print(); // 输出: a_ = 5, b_ = 0return 0;
}

在这个示例中,我们展示了如何使用 {} 初始化结构体、使用构造函数初始化类对象以及使用接受 std::initializer_list 的构造函数初始化类对象。

6 总结

C++11 中的列表初始化特性提供了一种更加简洁、直观和安全的初始化方式。它不仅统一了各种对象的初始化方式,而且还能在编译时捕捉窄化转换等潜在错误。因此,在 C++11 及之后的代码中,推荐使用列表初始化作为默认的初始化方式。通过深入理解并掌握这一特性,我们可以编写出更加健壮、可读和可维护的 C++ 代码。


http://www.mrgr.cn/news/52045.html

相关文章:

  • 【微信小程序_18_WXS脚本】
  • TemporalBench:一个专注于细粒度时间理解的多模态视频理解的新基准。
  • 从实习到春招成为一名安全工程师,我经历了什么
  • mqtt与云服务器
  • 2024了,传统行业转行AI,可不可行?
  • Java 虚拟机(JVM)中的内存泄漏排查技巧及各种内存查看命令分析工具推荐
  • C语言中点操作符(.)和箭头操作符(->)的区别
  • 汽车免拆诊断案例 | 2023款零跑C01纯电车后备厢盖无法电动打开和关闭
  • 对“一个中心,三重防护”中安全管理中心的理解
  • 数据结构深度优先搜索遍历连通图+非连通图(C语言代码+遍历+终端输入内容)
  • 超详细的B/S和C/S架构对比
  • 【PT-RS】
  • SIEMENS罗宾康LDZ14501001.140功率单元适合哪些场合使用?
  • 【论文阅读】03-Diffusion Models and Representation Learning: A Survey
  • 使用Python语言结合OpenCV库来处理视频流和条形码/二维码的识别
  • 代码随想录算法训练营第三十七天|509. 斐波那契数,70. 爬楼梯,746. 使用最小花费爬楼梯
  • YOLO的正负样本分配策略
  • 【Linux】/usr/share目录
  • v853扬声器调试
  • YOLO11改进-模块-引入Histogram Transformer Block(HTB)解决恶劣天气(雨雾雪)