首页 > 编程笔记 > C++笔记 阅读:27

C++列表初始化的用法(非常详细,附带实例)

列表初始化是 C++11 引入的一个重要特性,提供了一种统一和直观的方式来初始化对象。

从 C++ 11 标准开始,程序中可以使用花括号({})来初始化各种类型的数据,包括基本类型、聚合类型、容器以及用户自定义类型。列表初始化的语法简洁、使用灵活,是现代 C++ 推荐的初始化方式之一。

列表初始化的特点:

C++列表初始化的适用场景

1) 基本数据类型

列表初始化可以用于直接设定基础数据类型的值,例如:
int x{5};

2) 聚合类型

结构体和数组可以通过列表初始化直接设定所有成员或元素的值,例如:
struct Point{ int x, y; };
Point p {1, 2};

3) 容器和其他类类型

对于支持 initializer_list 的容器(如 std::vector 或 std::map),列表初始化提供了一种方便的方式一次性填充容器,例如:
std::vector<int> v = {1, 2, 3};

4) 自定义类型

用户定义的类可以设计构造函数支持列表初始化,提高类的易用性和灵活性。

C++列表初始化的限制

1) 没有公共构造函数的类型

对于构造函数为 private 或 protected 的类,普通代码不能直接使用列表初始化。只有类内部或友元类/函数才可以使用。

2) 非聚合类型且无适当构造函数的类

如果一个类不是聚合类型(即具有私有或受保护的成员、基类、虚函数等),同时也没有定义接收 std::initializer_list 或其他形式参数的构造函数,则无法通过列表初始化进行初始化。

3) 引用类型

引用必须绑定到一个现有对象,不能通过列表初始化直接创建引用。

例如,int& ref{value};是合法的,因为引用绑定到 value,但尝试使用 int& ref{} 形式的初始化将会导致编译错误。

4) 复杂构造逻辑的类型

对于需要执行逻辑或多个参数的构造函数,如果未定义接收 std::initializer_list 的构造函数,可能无法使用列表初始化,因为列表提供确保正确匹配构造函数的参数。

5) 某些内建类型的数组

当数组元素的类型不支持列表初始化时,数组也无法使用列表初始化。

以上情况基本涵盖了不能使用列表初始化的主要类型。在实际编程中,当遇到无法使用列表初始化的情况时,通常需要回退到传统的构造函数调用或其他初始化方式。

【实例】下面是一个综合代码示例,展示了如何使用列表初始化来初始化聚合类型、非聚合类型以及容器。
#include <iostream>
#include <vector>
#include <string>
// 聚合类型:结构体
struct Point {
    int x;
    int y;
};
// 非聚合类型:类定义
class Circle {
public:
    double radius;
    Circle(double r) : radius(r) {}  // 自定义构造函数
};
// C++17 聚合类型可以有基类(此特性需要编译器支持 C++20 的完整实现,部分编译器可能仅在 C++20 模式下支持)
struct Base {
    int baseValue;
};
// 聚合类型
struct Derived : public Base { // C++17 允许聚合类型有公有基类
    int x;
    double y;
};
int main() {
    // 聚合类型的列表初始化
    Point p {10, 20};
    std::cout << "Point: (" << p.x << ", " << p.y << ")" << std::endl;
    // C++17 聚合初始化,包括基类成员
    Derived d = {{1}, 2, 3.5};
    std::cout << "Derived: baseValue(" << d.baseValue << "), x(" << d.x << "), y(" << d.y << ")" << std::endl;
    // 非聚合类型的列表初始化
    Circle c {5.0};
    std::cout << "Circle radius: " << c.radius << std::endl;
    // 容器的列表初始化
    std::vector<std::string> names {"Alice", "Bob", "Charlie"};
    std::cout << "Names:";
    for (const auto& name : names) {
        std::cout << " " << name;
    }
    std::cout << std::endl;
    return 0;
}
运行结果为:

Point: (10, 20)
Derived: baseValue(1), x(2), y(3.5)
Circle radius 5
Names: Alice Bob Charlie

这个示例展示了列表初始化在聚合类型、非聚合类型以及容器中的应用,说明了其灵活性和在现代 C++ 编程中的实用性。

相关文章