目录
1. initializer_list
2. 用initializer_list来实现列表构造vector
用列表初始化就是用"{}"来初始化你的vector等自定义实现的容器。我们可以看到STL库中给出的vector,list,map等等容器都是可以用"{}"的方式来初始化的,例如:
vectorv{ 1, 2, 3, 4, 5, 6, 7, 8, 9 }; list l={ 1, 2, 3, 4, 5, 6, 7, 8, 9 }; map m = { { 1, 1 }, { 2, 2 }, { 3, 3 } };
那么它是如何实现的呢?其实它具体的实现方式并没有你现象中的那么高大上,他是用一个initializer_list的容器来接收"{}"中的元素然后通过给出一个以initializer_list为参数列表的构造函数然后实现通过"{}"来构造容器。
1. initializer_list
先来介绍一下initializer_list:
可以看到他是C++11中才有的,那么也就说明之前C++98是不支持用列表构造对象的。它只有三个方法
我们来测试一下
2. 用initializer_list来实现列表构造vector
这里我将vector模拟实现的全部代码给出以免遭有些读者对于vector当中的具体实现细节不明白而不明白如何用列表来实现vector的构造:我还会将用initializer_list部分代码单独拿出来说明。(这里如果对vector模拟实现的代码有疑问可以看我对vector模拟实现的博客的详细解析:http://t.csdn.cn/vDdJ9http://t.csdn.cn/vDdJ9)
#include#include #include #include using namespace std; namespace wbx { template class vector { public: typedef T* iterator; typedef const T* const_iterator; /构造和析构 vector() :_start(nullptr) , _finish(nullptr) , end_of_storage(nullptr) {} //用列表构造vector: vector(initializer_list l) { _start = new T[l.size()]; _finish = _start; auto it = l.begin(); while (it != l.end()) { *_finish = *it; _finish++; it++; } end_of_storage = _finish; } //用列表赋值vector: vector & operator=(initializer_list l) { reserve(l.size()); _finish = _start; auto it = l.begin(); while (it != l.end()) { *_finish = *it; _finish++; it++; } return *this; } vector(size_t n, const T &val = T())//构造n个T类型的val值 :_start(nullptr)//指针要初始化这是一个良好的编程习惯 ,_finish(nullptr) ,end_of_storage(nullptr) { _start = new T[n*sizeof(T)]; _finish = _start+n; end_of_storage = _finish; for (size_t i = 0; i < n; i++) { _start[i] = val; } } vector(int n,const T &val = T())//构造n个T类型的val值,这里的val必须要用const修饰不然当传入参数时是编译通过不了的 :_start(nullptr)//指针要初始化这是一个良好的编程习惯 , _finish(nullptr) , end_of_storage(nullptr) { _start = new T[n*sizeof(T)]; _finish = _start + n; end_of_storage = _finish; for (int i = 0; i < n; i++) { _start[i] = val; } } vector(const vector &v)//拷贝构造 :_start(nullptr), _finish(nullptr), end_of_storage(nullptr) { //vector temp(v.begin(), v.end());//这里不可以调用普通类型的返回迭代器的指针, vector temp(v.cbegin(), v.cend());//因为const对象只能调用const类型的成员函数 this->swap(temp); } template //这里要再定义一个迭代器类的模板,因为这里假设我们vector中存放的不同类型对象 //所返回的迭代器类型也是不同的,所以我们这里重新设置一个模板类对于多种不同 //类型具有普遍的适用性 vector(Iterator first, Iterator last) { size_t n = last - first; //这里获取frist和last之间的距离应当写一个distance函数来 //获取他们之间的距离,这里这样写是因为简单模拟实现 _start = new T[n]; _finish = _start; end_of_storage = _start + n; while (first != last) { *_finish = *first; _finish++; first++; } } ~vector() { if (_start) { delete[] _start; _start = nullptr; _finish = nullptr; end_of_storage = nullptr; } } 运算符重载: vector operator=(vector v) { this->swap(v); return *this; } T& operator[](size_t index) { if (index < 0 || index >= size()) { assert(false); } return *(_start + index) ; } ///容量相关 size_t size() { int a = 0; return a=_finish - _start; } size_t capacity() { return end_of_storage - _start; } bool empty() { if (_start == _finish) { return true; } return false; } void resize(size_t n, T val = T()) { size_t oldsize = size(); if (n >capacity()) { reserve(n - capacity()); } for (int i = oldsize; i < n; i++) { _start[i] = val; } _finish = _start + n;//如果新的size小于老的size这里直接访问不到了 } void reserve(size_t n) { if (n>capacity()) { T *temp = new T[n]; for (int i = 0; i < size(); i++) { temp[i] = _start[i];//这里必须要用=来进行拷贝如果用其他如memcpy的话就会发生浅拷贝的情况 } size_t oldsize = size(); if (_start) { delete[] _start; } _start = temp; _finish = _start + oldsize; end_of_storage = _start + n; } } 迭代器 iterator begin() { return _start; } iterator end() { return _finish; } const_iterator cbegin()const { return _start; } const_iterator cend()const { return _finish; } /插入函数 void push_back(T val) { if (_finish == end_of_storage) { reserve(2 * capacity()); } *_finish = val; _finish++; } void pop_back() { if (empty()) { assert(false); } _finish--; } iterator insert(iterator pos,T val) { if (empty()||pos==_finish) { push_back(val); return pos; } if (_finish == end_of_storage) { reserve(capacity() + 1); } iterator temp = _finish-1; while (temp >= pos) { *(temp + 1) = *temp; temp--; } *pos = val; _finish++; return pos; } iterator erase(iterator pos) { if (pos < _start || pos >= _finish) { assert(false); } iterator ret = pos; while (pos != _finish - 1) { *pos = *(pos + 1); pos++; } _finish--; return ret + 1; } T & front() { return *(_start); } T &back() { return *(_finish-1); } 交换函数 void swap(vector &v) { std::swap(v._start, _start); std:: swap(v._finish, _finish); std::swap(v.end_of_storage, end_of_storage); } private: iterator _start; iterator _finish; iterator end_of_storage; }; } using namespace std; wbx::vector static v4(5, 4); void test1() { wbx::vector v1{ 1, 2, 3, 4, 5, 6, 7, 8, 9 }; cout << "v1: "; for (int i = 0; i < v1.size(); i++) { cout << v1[i] << " "; } cout << endl; wbx::vector v2; v2 = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; cout << "v2: "; for (int i = 0; i < v2.size(); i++) { cout << v2[i] << " "; } cout << endl; wbx::vector v3(11); v3 = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; cout << "v3: "; for (int i = 0; i < v3.size(); i++) { cout << v3[i] << " "; } cout << endl; cout << v1.size() << endl; cout << v2.size() << endl; cout << v3.size() << endl; cout << v1.capacity() << endl; cout << v2.capacity() << endl; cout << v3.capacity() << endl; }
关于initializer_list部分代码:可以看到实现是十分简单的,就是用initializer_list内部的元素对vector空间循环赋值。
//用列表构造vector: vector(initializer_listl) { _start = new T[l.size()];//这里的start是vector底层管理数组空间的指针起始地址 _finish = _start; auto it = l.begin(); while (it != l.end()) { *_finish = *it;//finish是vector底层数组的结束位置 _finish++; it++; } end_of_storage = _finish;//end_of_storage是vector所开辟空间的结束位置 } //用列表赋值vector: vector & operator=(initializer_list l) { reserve(l.size()); _finish = _start; auto it = l.begin(); while (it != l.end()) { *_finish = *it; _finish++; it++; } return *this; }



