c++11初始化列表(initializer_list)

目录

写在前面

详述

initializer_list部分源码

方法

使用

参考文献


写在前面

c++11标准中,initializer_list对于标准库的编写影响非常大,说一个简单的例子,在c++11之前,max函数的源程序是这样的:

template <class T> const T& max (const T& a, const T& b);
template <class T, class Compare>
  const T& max (const T& a, const T& b, Compare comp);  //支持自己编写的比较函数

也就是max函数只能比较两者之间的大小,但是有了initializer_list后,c++11标准库中添加另外一种实现方式:

template <class T> T max (initializer_list<T> il);
template <class T, class Compare>
  T max (initializer_list<T> il, Compare comp);

这就说明,c++11之后,max函数可以传递更多的参数,栗子:

cout << max({ 54,16,48,5 }) << endl;   //输出54

可以说:initializer_list是某种类型的数组,但是内部数据都是const T类型,可以整体作为参数传递,由{}进行初始化

详述

c++11中统一了初始化列表(Uniform Initiaization),即均可以使用{}来对对象进行初始化。例如:

int value[]{1,2,3};
vector<int> v{2,3,4,5,6,7};
vector<string> cities{"Beijing","Dezhou"};
int i;         //i has undefined value
int j{};       //j is initialized by 0
int *p;        //p has undfined value
int *q{};      //q is initialized by nullptr

我们使用{}可以给上面进行赋值,那如果是结构体呢?

struct Peo
{
	std::string name;
	int pos;
};
Peo p[2]{ {"abo",1},{"abo2",2} };

综上,上面的初始化列表背后就是使用initializer_list来进行实现的,比如vector和map的构造函数中新增了这样一种新的构造函数:

vector (initializer_list<value_type> il,
       const allocator_type& alloc = allocator_type());   //vector使用initializer_list进行初始化
map (initializer_list<value_type> il,
     const key_compare& comp = key_compare(),
     const allocator_type& alloc = allocator_type());  //map使用initializer_list进行初始化

这样才支持使用初始化列表来对其进行初始化

并且初始化列表可以放置类型转换精度的损失,比如:

nt x{1.1};     //[Warning] narrowing conversion of '1.1000000000000001e+0' from 'double' to 'int' inside { } [-Wnarrowing]   在dev c++ GCC4.9.2 条件下编译
//可能在其他编译器条件下编译会产生错误

initializer_list部分源码

  public:
      typedef _E 		value_type;
      typedef const _E& 	reference;
      typedef const _E& 	const_reference;
      typedef size_t 		size_type;
      typedef const _E* 	iterator;
      typedef const _E* 	const_iterator;

    private:
      iterator			_M_array;         //起点指针
      size_type			_M_len;           //总共长度

      // The compiler can call a private constructor.   编译器可以调用的构造函数版本
      constexpr initializer_list(const_iterator __a, size_type __l)
      : _M_array(__a), _M_len(__l) { }

    public:
      constexpr initializer_list() noexcept            //public的构造函数版本
      : _M_array(0), _M_len(0) { }

可以看到在initializer_list内部数据部分只包含一个起点指针,以及一个总共长度,在侯捷老师的课程中提及到initializer_list背后是由array实现的,声明一点:The initializer_list object refers to the elements of this array without containing(内含) them(initializer_list并没有内涵这些元素)所以我们在做拷贝的时候,特别注意是否为浅拷贝,并且保存的数据均为const T类型,不可以对数据进行修改

方法

constructor方法

构造函数
size 返回initializer_list的长度
begin 开始元素指针    或者使用begin(initializer_list<T> __ils)方法获取
end 结尾元素指针    或者使用 end(initializer_list<T> __ils)方法获取

使用

initializer_list对象的构造方式:当编译器看到{t1,t2...tn}遍做出一个initializer_list(同时关联到一个array<T,n>  n表示个数),调用函数时,array中的元素可被编译器分解逐一传给参数,但是如果函数参数是一个initializer_list,则会统一传入参数。

	for(auto x:{1,2,3,4,5})
		cout << x << endl;	

使用比较笨拙的方式自己实现了_vector,主要为了说明initializer_list的用法

#include <iostream>
#include <initializer_list>
#include <algorithm>
#include <array>
#include <map>
#include <queue>
using namespace std;

template<typename T>
class _vector
{
public:
	_vector(initializer_list<T> _tmp)
	{
		len = _tmp.size();
		_a = new int [ len+1 ];
		int index = 0;
		for(T _x:_tmp)
			_a[index++] = _x;		
	}	
	~_vector()
	{
		delete []_a;    //new时使用[],delete中可要使用[] 
	}
	void append(initializer_list<T> _tmp)
	{
		
		int newlen = len + _tmp.size();
		T *_now = new int [newlen];     //比较笨拙的方法重新开辟空间 
 		
		copy(_a,_a+len,_now);          //之前内容拷贝 
			 
		delete []_a;                   //空间释放 
		for(T _x:_tmp)                 //内容衔接 
			_now[len++] = _x;
		_a = _now;                     //将_a指向新空间首地址 
	}
	
	void show()
	{
		for_each(_a,_a+len,[](T _tmp){
			cout << _tmp << endl;
		});
	}
		
private:
	T *_a;	//直接使用数组模拟实现,实质vector内部内存分配非常巧妙	
	int len;
};

int main()
{	
	_vector<int> vec = {1,2,3,4,5};
	vec.append({6,7,8});
	vec.show();
	
	return 0;
}

参考文献

http://www.cplusplus.com/reference/

侯捷老师关于C++2.0新特性的讲解,视频来自B站 https://www.bilibili.com/video/av20944273,原视频网址 http://boolan.com/

猜你喜欢

转载自blog.csdn.net/li1615882553/article/details/86529889