C++11中std::initializer_list的使用

initializer_list是一种标准库类型,用于表示某种特定类型的值的数组。和vector一样,initializer_list也是一种模板类型,定义initializer_list对象时,必须说明列表中所含元素的类型。和vector不一样的是,initializer_list对象中的元素永远是常量值,我们无法改变initializer_list对象中元素的值。

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

作用于initializer_list对象的begin和end操作类似于vector对应的成员。begin()成员提供一个指向列表首元素的指针,end()成员提供一个指向列表尾元素的指针。

含有initializer_list形参的函数也可以同时拥有其他形参。

类模板initializer_list用于访问初始化列表(initialization list),列表元素的数据类型为const T.编译器从花括号(brace)封闭的、元素由逗号分隔开的初始化列表自动构造initializer_list模板类, 例如:

auto il = {10,20, 30}; // the type of il is an initializer_list<int>
类模板initializer_list引用(refer to)但不包含这个这个列表的元素。复制这个initializer_list对象将引用到同一个基础列表而不是引用到基础列表的新的拷贝。std::initializer_list并不是一个容器,不要用它传递期望长期存储的值。构造函数的形参如果为一个initializer_list模板类,则这种特殊的构造函数称为初始化器列表构造函数(initializer_list constructor),例如:

struct myclass {
  myclass (int,int);
  myclass (initializer_list<int>);
  /* definitions ... */
};
myclass foo {10,20};  // calls initializer_list constructor
myclass bar (10,20);  // calls first constructor 

仅可以从braced-init-list推导出initializer_list<T>。这一过程中,编译器自动查询哪些构造函数可以用initializer_list<T>作为参数,并据此确定initializer_list的模板参数T的类型,从而对braced-init-list做类型转换。

C++11标准明确规定不能由模板参数推导出对应实参std::initializer_list的类型。

C++还有一种特殊的形参类型(即省略符),可以用它传递可变数量的实参。

省略符形参是为了便于C++程序访问某些特殊的C代码而设置的,这些代码使用了名为varargs的C标准库功能。通常,省略符形参不应用于其他目的。省略符形参只能出现在形参列表的最后一个位置。

  std::initializer_list:This type is used to access the values in a C++ initialization list, which is a list of elements of type const T.

下面是从其它文章中copy的std::initializer_list测试代码,详细内容介绍可以参考对应的reference:

#include "initializer_list.hpp"
#include <initializer_list>
#include <iostream>
#include <string>
#include <sstream>
#include <vector>

///
// reference: http://www.cplusplus.com/reference/initializer_list/initializer_list/
struct myclass {
	std::string str;
	myclass(std::initializer_list<int> args) {
		std::stringstream ss;
		std::initializer_list<int>::iterator it;  // same as: const int* it
		for (it = args.begin(); it != args.end(); ++it) ss << ' ' << *it;
		str = ss.str();
	}
};

template<class T>
struct simple_container {
	T * data;
	unsigned n;
	simple_container(std::initializer_list<int> args) {
		data = new T[args.size()];
		n = 0;
		for (T x : args) { data[n++] = x; }
	}
	T* begin() { return data; }
	T* end() { return data + n; }
};

template<class T>
void print_list(std::initializer_list<T> il)
{
	for (const T* it = std::begin(il); it != std::end(il); ++it) std::cout << ' ' << *it;
	std::cout << '\n';
}

int test_initializer_list_1()
{
{
	std::initializer_list<int> mylist;
	mylist = { 10, 20, 30 };
	std::cout << "mylist contains:";
	for (int x : mylist) std::cout << ' ' << x;
	std::cout << '\n';
}

{
	myclass myobject{ 10, 20, 30 };
	std::cout << "myobject contains:" << myobject.str << '\n';
}

{
	simple_container<int> myobject{ 10, 20, 30 };
	std::cout << "myobject contains:";
	for (int x : myobject) std::cout << ' ' << x;
	std::cout << '\n';
}

{
	print_list({ 10, 20, 30 });
}

{
	// 编译器从花括号(brace)封闭的、元素由逗号分隔开的初始化列表自动构造initializer_list模板类
	auto il = { 10, 20, 30 };
	for (auto i : il)
		std::cout << i << "    ";
	std::cout << std::endl;
}

	return 0;
}


// reference: http://en.cppreference.com/w/cpp/utility/initializer_list
template <class T>
struct S {
	std::vector<T> v;
	S(std::initializer_list<T> l) : v(l) {
		std::cout << "constructed with a " << l.size() << "-element list\n";
	}
	void append(std::initializer_list<T> l) {
		v.insert(v.end(), l.begin(), l.end());
	}
	std::pair<const T*, std::size_t> c_arr() const {
		return{ &v[0], v.size() };  // copy list-initialization in return statement
		// this is NOT a use of std::initializer_list
	}
};

template <typename T>
void templated_fn(T) {}

int test_initializer_list_2()
{
	S<int> s = { 1, 2, 3, 4, 5 }; // copy list-initialization
	s.append({ 6, 7, 8 });      // list-initialization in function call

	std::cout << "The vector size is now " << s.c_arr().second << " ints:\n";

	for (auto n : s.v)
		std::cout << n << ' ';
	std::cout << '\n';

	std::cout << "Range-for over brace-init-list: \n";

	for (int x : {-1, -2, -3}) // the rule for auto makes this ranged-for work
		std::cout << x << ' ';
	std::cout << '\n';

	auto al = { 10, 11, 12 };   // special rule for auto

	std::cout << "The list bound to auto has size() = " << al.size() << '\n';

	//    templated_fn({1, 2, 3}); // compiler error! "{1, 2, 3}" is not an expression,
	// it has no type, and so T cannot be deduced
	templated_fn<std::initializer_list<int>>({ 1, 2, 3 }); // OK
	templated_fn<std::vector<int>>({ 1, 2, 3 });           // also OK

	return 0;
}

GitHub:  https://github.com/fengbingchun/Messy_Test

回答: c++std::initializer_list是一个类模板,用于创建一个初始化器列表,它可以用来初始化标准容器或特定的自定义类对象。\[2\]它的底层机制是指针空间,类似于一个存放了一堆元素的列表。\[2\]你可以使用std::initializer_list来遍历列表的元素,通过使用begin()和end()函数来获取指向首元素和末尾元素后一位置的指针,然后使用循环来遍历列表的元素。\[1\]例如,你可以使用for循环来遍历一个std::initializer_list<int>对象,并使用*it来访问每个元素。\[2\]另外,你也可以使用size()函数来获取初始化器列表元素的数量。\[3\] #### 引用[.reference_title] - *1* *3* [C++std::initializer_list详解](https://blog.csdn.net/weixin_43165135/article/details/127927352)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [现代C++之std::initializer_list的特性分析](https://blog.csdn.net/a574780196/article/details/122493579)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值