当前位置:网站首页>用列表初始化你的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;
}
边栏推荐
- poj 2762 Going from u to v or from v to u? (infer whether it is a weak link diagram)
- Introduction to JVM
- 开源crm客户关系统管理系统源码,免费分享
- GFS分布式文件系統
- Idea rundashboard window configuration
- 保研笔记四 软件工程与计算卷二(8-12章)
- 98. Verify the binary search tree ●●
- 15 MySQL-存储过程与函数
- Rasa 3. X learning series -rasa x Community Edition (Free Edition) changes
- 11gR2 Database Services for &quot; Policy&quot; and &quot; Administrator&quot; Managed databases (file I
猜你喜欢
【原创】程序员团队管理的核心是什么?
开关电源Buck电路CCM及DCM工作模式
Do you regret becoming a programmer?
同事悄悄告诉我,飞书通知还能这样玩
保研笔记一 软件工程与计算卷二(1-7章)
Online yaml to CSV tool
《牛客刷verilog》Part III Verilog企业真题
The PNG image is normal when LabVIEW is opened, and the full black image is obtained when Photoshop is opened
Rasa 3. X learning series -rasa 3.2.1 new release
Comparison of parameters between TVs tube and zener diode
随机推荐
LeetCode——Add Binary
C# Linq Demo
TS type declaration
Development specification: interface unified return value format [resend]
Object detection based on impulse neural network
Spire. PDF for NET 8.7.2
From the perspective of quantitative genetics, why do you get the bride price when you get married
21.PWM应用编程
【原创】程序员团队管理的核心是什么?
Golang code checking tool
(4) UART application design and simulation verification 2 - RX module design (stateless machine)
idea 连接mysql ,直接贴配置文件的url 比较方便
【经典控制理论】自控实验总结
Convert Chinese into pinyin
TVS管和ESD管的技術指標和選型指南-嘉立創推薦
做自媒体影视短视频剪辑号,在哪儿下载素材?
Part III Verilog enterprise real topic of "Niuke brush Verilog"
Redis高可用——主从复制、哨兵模式、集群
STM32__ 06 - single channel ADC
20220703 周赛:知道秘密的人数-动规(题解)