C++11引入的初始化列表


列表初始化,也称为统一初始化或 初始化列表,是在 C++11标准中引入的。这种初始化方式允许使用花括号 {}来初始化对象,无论是自动变量、动态分配的对象,还是容器和数组等。列表初始化的引入增加了C++初始化方式的一致性和简洁性,并且提供了以下优点:

  • 防止窄化转换:在列表初始化中,从一种类型到另一种类型的窄化转换(可能导致数据丢失或改变的转换)是不允许的,编译器将会报错。

  • 用于自动类型推导:与auto关键字结合时,可以用于自动类型推导,简化变量声明。

  • 初始化聚合类型:可以用于初始化聚合类型,如数组、结构体等,而不需要调用构造函数。

  • 初始化容器:可以直接初始化STL容器,如std::vectorstd::map等。

示例代码:

// C++11及以后
struct S{
	int a;
	int b;
};
S s={1,2};//s.a=1; s.b=2;
std::vector<int> v = {1, 2, 3, 4, 5}; // 列表初始化
int arr[] = {1, 2, 3, 4, 5}; // 数组初始化
std::map<int, std::string> map = {
    {1, "one"},
    {2, "two"},
    {3, "three"}
}; // 容器初始化

C++11通过引入列表初始化,不仅使得语法更加统一和简洁,还增强了类型安全。

介绍容器initializer_list

std::initializer_list是C++11引入的一种轻量级容器,专门设计用来支持花括号初始化语法(即列表初始化)。它是一个模板类,定义在头文件<initializer_list>中。std::initializer_list主要用于函数参数,使得函数可以接受花括号包围的初始化器列表,这在初始化对象或调用函数时特别有用,尤其是当你希望函数接受任意数量的参数时。

1、std::initializer_list的特点:

  • initializer_list<type>:表示初始化列表中的元素类型都是type。它可以使用auto引用遍历或者迭代器遍历。
  • 它实际上就是一个这样的初始化列表:{type_item1,type_item2,····}
  • 不拥有其元素std::initializer_list并不拥有它包含的元素,它只是提供了对由编译器静态分配的数组的访问。因此,它的元素不能被修改(即std::initializer_list中的元素是只读的)。
  • 轻量级:它仅包含元素的数组的起始位置和元素数量两个信息,因此非常轻量。
  • 自动推导类型:在使用花括号初始化std::initializer_list对象时,编译器可以自动推导出列表中元素的类型。

2、特点示例:

    initializer_list<int> a={1,2,3,4,5};
    for(auto & i:a)
        cout<<i<<' ';
    cout<<endl;
    for(auto it=a.begin();it!=a.end();++it)
        cout<<*it<<' ';
    cout<<endl<<a.size();
1 2 3 4 5
1 2 3 4 5
5

3、使用示例:

使用std::initializer_list

#include <initializer_list>
#include <iostream>
vector<int> vec;
void print(std::initializer_list<int> il) {
	vec.assign(il);//il是一个初始化列表 等价于:vec.asiign({1, 2, 3, 4, 5});
    for (auto& e : il) {
        std::cout << e << ' ';
    }
    std::cout << '\n';
}

int main() {
    print({1, 2, 3, 4, 5});
}

下面是一些使用初始化列表的不同例子,展示其在C++中的多样性和便利性。

1. 初始化自定义对象集合

#include <initializer_list>
#include <iostream>
#include <vector>

class Point {
public:
    int x, y;
    Point(int x, int y) : x(x), y(y) {}
};

class Polygon {
    std::vector<Point> vertices;
public:
    Polygon(std::initializer_list<Point> points) : vertices(points) {}

    void print() {
        for (const auto& p : vertices) {
            std::cout << "(" << p.x << ", " << p.y << ") ";
        }
        std::cout << std::endl;
    }
};

int main() {
    Polygon poly = {{1, 2}, {3, 4}, {5, 6}};
    poly.print();
}

2. 使用初始化列表简化容器的初始化

#include <vector>
#include <iostream>

int main() {
    std::vector<std::string> names = {"Alice", "Bob", "Charlie"};
    for (const auto& name : names) {
        std::cout << name << std::endl;
    }
}

3. 函数参数为初始化列表

这可以使得函数接受任意数量的同类型参数。

#include <initializer_list>
#include <iostream>

void printSum(std::initializer_list<int> nums) {
    int sum = 0;
    for (auto num : nums) {
        sum += num;
    }
    std::cout << "Sum: " << sum << std::endl;
}

int main() {
    printSum({1, 2, 3, 4, 5}); // 输出: Sum: 15
}

4. 聚合类型初始化

在C++11及之后的版本中,聚合类型如数组和POD(Plain Old Data)结构体可以使用初始化列表。

#include <iostream>

struct Vec2 {
    float x, y;
};

int main() {
    Vec2 direction = {0.5, 0.75}; // 使用初始化列表初始化结构体
    int arr[] = {1, 2, 3, 4, 5}; // 使用初始化列表初始化数组

    std::cout << "Vec2: (" << direction.x << ", " << direction.y << ")" << std::endl;
    std::cout << "Array: ";
    for (int i : arr) {
        std::cout << i << ' ';
    }
    std::cout << std::endl;
}
  • 10
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Yorelee.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值