C++列表初始化的用法(非常详细,附带实例)
列表初始化是 C++11 引入的一个重要特性,提供了一种统一和直观的方式来初始化对象。
从 C++ 11 标准开始,程序中可以使用花括号({})来初始化各种类型的数据,包括基本类型、聚合类型、容器以及用户自定义类型。列表初始化的语法简洁、使用灵活,是现代 C++ 推荐的初始化方式之一。
列表初始化的特点:
例如,
以上情况基本涵盖了不能使用列表初始化的主要类型。在实际编程中,当遇到无法使用列表初始化的情况时,通常需要回退到传统的构造函数调用或其他初始化方式。
【实例】下面是一个综合代码示例,展示了如何使用列表初始化来初始化聚合类型、非聚合类型以及容器。
从 C++ 11 标准开始,程序中可以使用花括号({})来初始化各种类型的数据,包括基本类型、聚合类型、容器以及用户自定义类型。列表初始化的语法简洁、使用灵活,是现代 C++ 推荐的初始化方式之一。
列表初始化的特点:
- 防止窄化转换:列表初始化不允许窄化转换,这意味着编译器会阻止任何可能导致数据丢失或意外行为的隐式类型转换。例如,尝试用浮点数初始化整数时,如果使用列表初始化,编译器将拒绝编译。
- 直观的聚合类型初始化:对于聚合类型(如数组、结构体),列表初始化提供了简明的方式来一次性设置所有成员的值,而无须逐一指定。
- 兼容各种构造函数:如果类型定义了接收 std::initializer_list 参数的构造函数,列表初始化会自动匹配并调用此构造函数,使初始化更加灵活和方便。如果没有适合的 std::initializer_list 构造函数,编译器会尝试使用其他匹配的构造函数。
- 适用于自动类型推断:在使用 auto 关键字时,列表初始化允许编译器自动推断变量的类型,有助于减少代码冗余和提高可读性。
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