目录
- 1.初始化列表的实现
- 2. initializer_list模板
- 3.让自定义的类可以接受任意长度初始化列表
1.初始化列表的实现
(1)当编译器看到{t1,t2…tn}时便会生成一个initializer_list对象(其中的T为元素的类型),它关联到一个array。
(2)对于聚合类型,编译器会将array内的元素逐一分解并赋值给被初始化的对象。这相当于为该对象每个字段分别赋值。
(3)对于非聚合类型。如果该类存在一个接受initializer_list类型的构造函数,则初始化时会将initializer_list对象作为一个整体传给构造函数。如果不存在这样的构造函数,则array内的元素会被编译器分解并传给相应的能接受这些参数的构造函数(比如列表中有2个元素的,就传给带2个参数的构造函数。有3个元素的,就传给带3个参数的构造函数,依此类推……)。
【实例分析】initializer_list初体验
#include
#include
#include
2. initializer_list模板
//initializer_list源码分析
#include
template
class initializer_list
{
public:
typedef T value_type;
typedef const T& reference; //注意说明该对象永远为const,不能被外部修改!
typedef const T& const_reference;
typedef size_t size_type;
typedef const T* iterator; //永远为const类型
typedef const T* const_iterator;
private:
iterator _M_array; //用于存放用{}初始化列表中的元素
size_type _M_len; //元素的个数
//编译器可以调用private的构造函数!!!
//构造函数,在调用之前,编译会先在外部准备好一个array,同时把array的地址传入模板
//并保存在_M_array中
constexpr initializer_list(const_iterator __a, size_type __l)
:_M_array(__a),_M_len(__l){}; //注意构造函数被放到private中!
constexpr initializer_list() : _M_array(0), _M_len(0){} // empty list,无参构造函数
//size()函数,用于获取元素的个数
constexpr size_type size() const noexcept {return _M_len;}
//获取第一个元素
constexpr const_iterator begin() const noexcept {return _M_array;}
//最后一个元素的下一个位置
constexpr const_iterator end() const noexcept
{
return begin() + _M_len;
}
};
(1)initializer_list是一个轻量级的容器类型,内部定义了iterator等容器必需的概念,本质上是一个迭代器!
(2)对于std:: initializer_list而言,它可以接收任意长度的初始化列表,但要求元素必须是同种类型(T或可转换为T)。
(3)它有3个成员函数:size()、begin()和end()。
(4)拥有一个无参构造函数,可以被直接实例化,此时将得到一个空的列表。之后可以进行赋值操作,如initializer_list list; list={1,2,3,4,5};
(5)initializer_list在进行复制或赋值时,它内部将保存着列表的地址保存在_M_array中,它进行的是浅拷贝,并不真正复制每个元素,因此效率很高。
【编程实验】打印初始化列表的每个元素
#include
//打印初始化列表的每个元素
void print(std::initializer_list vals)
{
//遍历列表中的每个元素
for(auto p = vals.begin(); p!=vals.end(); ++p){
std::cout << *p << " ";
}
std::cout << std::endl;
}
//std::initializer_list的浅拷贝。以下的返回值应改为std
//以下的返回值应改为std::vector类型,而不是std::initializer_list类型。
std::initializer_list func(void)
int a = 1;
int b = 2;
return {a, b}; //编译器看到{a, b}时,会做好一个array对象(其生命
//期直至func结束),然后再产生一个initializer_list
//临时对象,由于initializer_list采用的是浅拷贝,当
//函数返回后array会被释放,所以无法获取到列表中的元素!
int main()
print({1,2,3,4,5,6,7,8,9,10});
print(func());
return 0;
/*测试结果:
e:\Study\C++11\7>g++ -std=c++11 test1.cpp
e:\Study\C++11\7>a.exe
1 2 3 4 5 6 7 8 9 10
*/
3.让自定义的类可以接受任意长度初始化列表
(1)自定义类中重载一个可接受initializer_list类型的构造函数
(2)在该构造函数中,遍历列表元素并赋值给相应的字段。
【编程实验】自定义类的初始化列表
#include
#include
到此这篇关于C++11中跳转initializer_list实现分析的文章就介绍到这了,更多相关C++11 initializer_list内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!