1. 什么是列表初始化
c++11的新特性支持列表初始化:将不定数量的初始值放在一对花括号里进行列表初始化,好处是提供一种统一的初始化方法;可对普通变量,类,stl容器使用;
2. std::initialize_list浅谈
那么列表初始化怎么实现的?
这种不定长的初始化列表是通过std::initializer_list来实现的,这是C++11新引入的一个模板类,通过将std::initializer_list作为构造函数的参数,我们自己的结构也可以实现通过不定长的初始化列表构造。
看看官网对于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.
Objects of this type are automatically constructed by the compiler from initialization list declarations, which is a list of comma-separated elements enclosed in braces:
auto il = { 10, 20, 30 }; // the type of il is an initializer_list
其特性如下:
- 编译器自动构造,当初始化的时候使用的是大括号初始化,被自动构造。包括函数调用时和赋值
- 其成员均为const型,不可更改,且元素类型必须一致
- 其模板类内保存const变量的指针(const _Elem *_First, const _Elem *_Last)
initializer_list没有类似initializer_list(int, int, int, ...)的构造函数,那么对于initializer_list<int> li = {100, 200, 300, 400, 500}是怎么初始化的呢?
原理为:
- 在栈上面分配一个数组。
- 取到数组的第一个和最后一个地址的下一个(
ebp-18h,ebp-2Ch). - 然后调用构造函数
initializer_list(const _Elem *_First_arg, const _Elem *_Last_arg) noexcept。 以上过程由编译器完成
对于Vector容器的使用
在vector中存在如下的构造函数:
vector(initializer_list<_Ty> _llist, const _Alloc&_Al = _Alloc()) : _Mybase(_Al)
{
Range_construct_or_tidy( _llist.begin(), _llist.end(), random_access_iterator_tag{} );
}
3. Vector内存分配与扩容
vector底层是一段连续的线性内存空间,等同于数组;使用三个迭代器(指针)来管理:
template <class _Ty, class _Alloc = allocator<_Ty>>
class vector
{
...
protected:
pointer _Myfirst;
pointer _Mylast;
pointer _Myend;
}
这里三个指针分别指向vector起始字节位置,最后一个元素的末尾字节以及整个vector容器所占内存空间的末尾字节; 通过灵活运用这 3 个迭代器,vector 容器可以轻松的实现诸如首尾标识、大小、容器、空容器判断等几乎所有的功能,比如:
当空间不够装下数据时就需要扩容:
- 自动申请另一片更大的空间(一般是当前容量的2倍);
- 把原来的数据拷贝过去,接着释放原来的那片空间; 这也就解释了,为什么 vector 容器在进行扩容后,与其相关的指针、引用以及迭代器可能会失效的原因。
为什么扩容每次是两倍的增长,而不是3或其他倍数?见知乎回答 www.zhihu.com/question/36…