IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 用列表初始化你的vector&&initializer_list简介 -> 正文阅读

[数据结构与算法]用列表初始化你的vector&&initializer_list简介

目录

1. initializer_list

?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;
		}

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-07-04 23:13:18  更:2022-07-04 23:14:54 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 23:42:49-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码