当前位置:网站首页>用列表初始化你的vector&&initializer_list简介
用列表初始化你的vector&&initializer_list简介
2022-07-05 23:31:00 【月半木斤】
目录
2. 用initializer_list来实现列表构造vector
用列表初始化就是用"{}"来初始化你的vector等自定义实现的容器。我们可以看到STL库中给出的vector,list,map等等容器都是可以用"{}"的方式来初始化的,例如:
vector<int> v{ 1, 2, 3, 4, 5, 6, 7, 8, 9 };
list<int> l={ 1, 2, 3, 4, 5, 6, 7, 8, 9 };
map<int, int> 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<iostream>
#include<assert.h>
#include<vector>
#include<initializer_list>
using namespace std;
namespace wbx
{
template<class T>
class vector
{
public:
typedef T* iterator;
typedef const T* const_iterator;
/构造和析构
vector()
:_start(nullptr)
, _finish(nullptr)
, end_of_storage(nullptr)
{}
//用列表构造vector:
vector(initializer_list<T> 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<T>& operator=(initializer_list<T> 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<T> &v)//拷贝构造
:_start(nullptr),
_finish(nullptr),
end_of_storage(nullptr)
{
//vector temp(v.begin(), v.end());//这里不可以调用普通类型的返回迭代器的指针,
vector<T> temp(v.cbegin(), v.cend());//因为const对象只能调用const类型的成员函数
this->swap(temp);
}
template<class Iterator>//这里要再定义一个迭代器类的模板,因为这里假设我们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 <T>operator=(vector<T> 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 <T> &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<int> static v4(5, 4);
void test1()
{
wbx::vector<int> 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<int> 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<int> 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_list<T> l)
{
_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<T>& operator=(initializer_list<T> l)
{
reserve(l.size());
_finish = _start;
auto it = l.begin();
while (it != l.end())
{
*_finish = *it;
_finish++;
it++;
}
return *this;
}
边栏推荐
猜你喜欢
Data analysis - Thinking foreshadowing
Live tiktok shop 2022 latest gameplay card slot overseas live e-commerce new traffic
开源crm客户关系统管理系统源码,免费分享
Neural structured learning - Part 2: training with natural graphs
Spire Office 7.5.4 for NET
20220703 周赛:知道秘密的人数-动规(题解)
Technical specifications and model selection guidelines for TVs tubes and ESD tubes - recommended by jialichuang
进击的技术er——自动化
Neural structured learning 4 antagonistic learning for image classification
《牛客刷verilog》Part III Verilog企业真题
随机推荐
Neural structured learning 4 antagonistic learning for image classification
Convert Chinese into pinyin
无刷驱动设计——浅谈MOS驱动电路
The interface of grafana tool displays an error, incluxdb error
Qcombox (rewrite) + qcompleter (auto completion, auto loading the drop-down options of qcombox, setting the background color)
GFS分布式文件系統
MySQL (1) -- related concepts, SQL classification, and simple operations
证明 poj 1014 模优化修剪,部分递归 有错误
MySQL (2) -- simple query, conditional query
做自媒体影视短视频剪辑号,在哪儿下载素材?
CIS基准测试工具kube-bench使用
芯源&立创EDA训练营——无刷电机驱动
Objective C message dispatch mechanism
【EF Core】EF Core与C# 数据类型映射关系
保研笔记二 软件工程与计算卷二(13-16章)
Neural structured learning - Part 2: training with natural graphs
C# 文件与文件夹操作
GFS分布式文件系统
如何提升口才
How to improve eloquence