首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

C++之std::initializer_list详解

  • 25-02-17 10:20
  • 4044
  • 5391
blog.csdn.net

相关文章系列:

C/C++中{}的用法总结(全)_c++ {}-CSDN博客

目录

1.引言

2.std::initializer_list的实现原理

3.容器的初始化

4.函数中使用std::initializer_list

5.自定义类型中使用std::initializer_list

6.迭代std::initializer_list

7. 在模板中使用std::initializer_list

8.std::initializer_list的限制

9.总结


1.引言

       std::initializer_list 是 C++11 中的一个特性,它允许你使用花括号 {} 中的值列表来初始化容器或数组。通常用于初始化标准库容器,比如 std::list、std::vector、std::set、std::map 以及数组, 也可以用于包含容器成员的自定义类。

       std::initializer_list可以作用于可变数量的实参:有时我们无法提前预知应该向函数传递几个实参。为了编写能处理不同数量实参的函数,C++11新标准提供了两种主要的方法:如果所有的实参类型相同,可以传递一个名为std::initializer_list的标准库类型;如果实参的类型不同,我们可以编写一种特殊的函数,也就是所谓的可变参数模板。

2.std::initializer_list的实现原理

先看一下它的实现:

  1. template <class _Elem>
  2. class initializer_list {
  3. public:
  4. using value_type = _Elem;
  5. using reference = const _Elem&;
  6. using const_reference = const _Elem&;
  7. using size_type = size_t;
  8. using iterator = const _Elem*;
  9. using const_iterator = const _Elem*;
  10. constexpr initializer_list() noexcept : _First(nullptr), _Last(nullptr) {}
  11. constexpr initializer_list(const _Elem* _First_arg, const _Elem* _Last_arg) noexcept
  12. : _First(_First_arg), _Last(_Last_arg) {}
  13. _NODISCARD constexpr const _Elem* begin() const noexcept {
  14. return _First;
  15. }
  16. _NODISCARD constexpr const _Elem* end() const noexcept {
  17. return _Last;
  18. }
  19. _NODISCARD constexpr size_t size() const noexcept {
  20. return static_cast<size_t>(_Last - _First);
  21. }
  22. private:
  23. const _Elem* _First;
  24. const _Elem* _Last;
  25. };
  26. // FUNCTION TEMPLATE begin
  27. template <class _Elem>
  28. _NODISCARD constexpr const _Elem* begin(initializer_list<_Elem> _Ilist) noexcept {
  29. return _Ilist.begin();
  30. }
  31. // FUNCTION TEMPLATE end
  32. template <class _Elem>
  33. _NODISCARD constexpr const _Elem* end(initializer_list<_Elem> _Ilist) noexcept {
  34. return _Ilist.end();
  35. }

从中可以明白:

1)std::initializer_list提供的迭代器都是const _Elem*,因此它不能修改参数的值的。

  1. using iterator = const _Elem*;
  2. using const_iterator = const _Elem*;

2)当使用花括号初始化语法时,编译器会生成一个 std::initializer_list 对象。这个对象内部实际上包含两个指针:一个指向数组(或类似数组的结构)的开始位置,另一个指向结束位置(即下一个元素的起始位置,但不包括该位置)。

3)由于只存储了两个指针,std::initializer_list 的大小相对固定,通常是两个指针的大小,与它所包含的元素的数量无关。

4)std::initializer_list 对象的生命周期是与其所在的函数或表达式相绑定的。这意味着,一旦离开了初始化列表所在的上下文(如函数参数传递、容器初始化等),std::initializer_list 对象就会失效,其指向的数据也可能不再有效。

5)std::initializer_list内部不存储对象,可以认为它只是实际对象的一个视图。因此,通常不建议将 std::initializer_list 作为类的成员变量存储,因为它不能长期持有数据。

6)它拥有容器部分的特性:迭代器;因此它广泛用于一些容器和数组。

7)std::initializer_list特化了std::begin()和std::end(),使得它的应用场景更加广泛。

8)它也常用于函数参数,特别是当函数需要处理多个同类型参数时,使用 std::initializer_list 可以使函数接口更加简洁和灵活。

3.容器的初始化

使用std::initializer_list可以方便地初始化STL容器。在STL的很多容器都支持用std::initializer_list来构造,包括 std::list、std::vector、std::set、std::map等,如:

std::vector的构造函数:

  1. _CONSTEXPR20_CONTAINER vector(initializer_list<_Ty> _Ilist, const _Alloc& _Al = _Alloc())
  2. : _Mypair(_One_then_variadic_args_t{}, _Al) {
  3. auto&& _Alproxy = _GET_PROXY_ALLOCATOR(_Alty, _Getal());
  4. _Container_proxy_ptr<_Alty> _Proxy(_Alproxy, _Mypair._Myval2);
  5. _Range_construct_or_tidy(_Ilist.begin(), _Ilist.end(), random_access_iterator_tag{});
  6. _Proxy._Release();
  7. }

std::list的构造函数:

  1. list(initializer_list<_Ty> _Ilist) : _Mypair(_Zero_then_variadic_args_t{})
  2. {
  3. _Construct_range_unchecked(_Ilist.begin(), _Ilist.end());
  4. }

std::map的构造函数:

  1. map(initializer_list _Ilist) : _Mybase(key_compare())
  2. {
  3. insert(_Ilist);
  4. }

std::set的构造函数:

  1. set(initializer_list _Ilist) : _Mybase(key_compare())
  2. {
  3. this->insert(_Ilist);
  4. }

等等,示例如下:

  1. std::vector<int> a = {13, 32, 43, 54, 56};
  2. std::set<int> b= {1, 2, 33, 4, 5, 2};
  3. std::map<int, char> c= {{13, a}, {24, b}, {3666, c}};

4.函数中使用std::initializer_list

可以将 std::initializer_list 用作函数的参数,以便在函数调用时传递一组值。例如:

  1. void func(std::initializer_list<int> values) {
  2. // 使用初始化列表中的值
  3. for (const auto& value : values) {
  4. // 处理每个值
  5. }
  6. }
  7. // 调用函数
  8. func({13, 24, 35, 34, 52});

5.自定义类型中使用std::initializer_list

类的构造函数可以接受 std::initializer_list 参数,以便在创建对象时使用初始化列表进行初始化。例如:

  1. class MyContainer {
  2. public:
  3. MyContainer(std::initializer_list<int> list) : data(list) {
  4. std::cout << "MyContainer initialized with " << data.size() << " elements." << std::endl;
  5. }
  6. private:
  7. std::vector<int> data;
  8. };
  9. MyContainer c = {1, 2, 3, 4};

6.迭代std::initializer_list

可以使用范围基于的for循环或迭代器来遍历std::initializer_list。例如:

  1. std::initializer_list<int> list = {1, 2, 3, 4};
  2. for (int n : list) {
  3. std::cout << n << " ";
  4. }
  5. std::cout << std::endl;
  6. for (auto it = list.begin(); it != list.end(); ++it) {
  7. std::cout << *it << " ";
  8. }
  9. std::cout << std::endl;

7. 在模板中使用std::initializer_list

std::initializer_list在模板编程中也很有用,允许创建接受不定数量参数的泛型函数或类。例如:

  1. template<typename T>
  2. void printAll(std::initializer_list list) {
  3. for (const auto& item : list) {
  4. std::cout << item << " ";
  5. }
  6. std::cout << std::endl;
  7. }
  8. printAll({1, 2, 3, 4});
  9. printAll({"1241", "23525", "3252352"});

8.std::initializer_list的限制

1) std::initializer_list只能存储相同类型的元素。

2)  std::initializer_list内的元素不能被修改(它们是常量)。

  1. std::initializer_list<int> list = {1, 2, 3, 4};
  2. // list[0] = 10; // 错误:不能修改initializer_list中的元素

9.总结

从上面可以看到,使用std::initializer_list的优点:

1) 灵活性和扩展性:std::initializer_list可以用在任何需要可变数量参数的函数中,提供了高度的灵活性和扩展性。例如,你可以写一个接受std::initializer_list 参数的函数,让它可以接受任意数量的元素进行初始化。

2) 比 std::vector 更轻量和高效:  当你使用std::initializer_list作为形参时,在值传递过程中,只包括一个指向初始化列表元素的指针和一个表示元素数量的整数。

参考:

std::initializer_list - cppreference.com

注:本文转载自blog.csdn.net的流星雨爱编程的文章"https://blog.csdn.net/haokan123456789/article/details/137569063"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2492) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

101
推荐
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2025 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top