c++中vector的使用和模拟实现

一、接口介绍

1、插入数据

void push_back(const T& x)

在当前vector尾部插入x,如果容量不够扩大二倍。

iterator insert(iterator pos, const T& x)

在POS位置插入元素x

2、容量相关

size_t capacity()

返回当前vector的容量(size+剩余容量)

size_t size()

返回当前vector的元素个数

void resize(size_t n, const T& val = T())

改变当前vector的size,如果n>size则大于部分初始值为val。(capacity的大小始终保持不变)

void reserve(size_t n)

改变当前vector的capacity,如果n<capacity则不改变。

3、删除数据

void pop_back()

如果vector不为空,删除当前vector的最后一个元素

iterator erase(iterator pos)

删除POS位置的元素

4、运算符重载

T& operator[](size_t pos)

[]运算符重载,支持使用下标访问vector

二、实现

#include<iostream>
#include<string.h>
#include<assert.h>
using namespace std;

namespace myvector
{
	template<class T>
	class vector
	{
	public:
		typedef T* iterator;

		iterator begin()
		{
			return start;
		}

		iterator end()
		{
			return finish;
		}

		//默认构造函数
		vector()
			:start(nullptr)
			, finish(nullptr)
			, end_of_storage(nullptr)
		{}
		//容量
		size_t capacity()
		{
			return end_of_storage - start;
		}

		size_t size()
		{
			return finish - start;
		}

		void reserve(size_t n)
		{
			if (n > capacity())
			{
				//开新空间
				T* tmp = new T[n];
				//拷贝旧空间的内容
				memcpy(tmp, start, sizeof(T)*size());
				//改变容量
				finish = tmp + size();
				end_of_storage = tmp + n;
				//释放旧空间
				T* tmp1 = start;
				start = tmp;
				tmp = nullptr;
			}
		}

		void resize(size_t n, const T& val = T())
		{
			//判断容量
			if (n > capacity())
				reserve(n);
			//如果n<size
			if (n < size())
			{
				finish = start + n;
			}
			else
			{
				while (finish != start + n)
				{
					*finish = val;
					finish++;
				}
			}
		}
		//检查空间
		void check_capacity()
		{
			if (finish == end_of_storage)
			{
				//如果当前不为空,就扩2倍,为空就开4个吧
				size_t newcapacity = finish == nullptr ? 4 : capacity()*2;
				reserve(newcapacity);
			}
		}

		T& operator[](size_t pos)
		{
			assert(pos < size());
			return start[pos];
		}

		//插入
		void push_back(const T& x)
		{
			insert(finish,x);
		}

		iterator insert(iterator pos, const T& x)
		{
			assert(pos >= start && pos <= finish);
			size_t pos1 = pos - start;
			check_capacity();
			//解决迭代器失效
			pos = start + pos1;
			//移动数据
			iterator end = finish;
			while (end >= pos)
			{
				*(end + 1) = *end;
				end--;
			}
			//插入数据
			*pos = x;
			finish++;
			return pos;
		}

		//删除数据
		void pop_back()
		{
			assert(finish > start);
			finish--;
		}
		iterator erase(iterator pos)
		{
			assert(pos >= start && pos < finish);

			iterator it = pos + 1;
			while (it != finish)
			{
				*(it - 1) = *it;
				++it;
			}
			--finish;

			return pos;
		}
		//析构函数
		~vector()
		{
			delete[] start;
			start = finish = end_of_storage = nullptr;
		}
	private:
		iterator start;
		iterator finish;
		iterator end_of_storage;
	};
}

三、测试用例

void test1()
{
	//测试默认构造和析构函数
	myvector::vector<int> v1;

}

void test2()
{
	//测试push_back()、reserve、check_capacity、size、capacity
	myvector::vector<int> v2;

	//插入至少五个数据,进行一次扩容,扩容间接对size和capacity以及check_capacity进行了测试
	v2.push_back(1);
	v2.push_back(2);
	v2.push_back(3);
	v2.push_back(4);
	//v2.push_back(5);
	for (size_t i = 0; i < v2.size(); i++)
		cout << v2[i] << " ";
	cout << endl;

	//测试resize,变小变大
	v2.resize(8,6);
	for (size_t i = 0; i < v2.size(); i++)
		cout << v2[i] << " ";
	cout << endl;
	v2.resize(4);

	//测试[]
	//正常访问
	for (size_t i = 0; i < v2.size(); i++)
		cout << v2[i] << " ";
	cout << endl;
	//越界访问
	//cout << v2[v2.size()] << endl;
	//cout << v2[-1] << endl;

	//测试insert---将push_back使用insert插入也可以进行检查
	myvector::vector<int>::iterator it = v2.begin();
	it = v2.insert(it,0);
	it = v2.insert(it + 2, 10);
	for (size_t i = 0; i < v2.size(); i++)
		cout << v2[i] << " ";
	cout << endl;

	//测试删除
	v2.pop_back();
	v2.pop_back();
	for (size_t i = 0; i < v2.size(); i++)
		cout << v2[i] << " ";
	cout << endl;
	v2.erase(v2.begin());
	for (size_t i = 0; i < v2.size(); i++)
		cout << v2[i] << " ";
	cout << endl;
}

四、迭代器失效

1、在vector的接口中,使用insert插入数据时可能导致迭代器失效,具体如下

2、删除操作导致迭代器失效

3、迭代器失效的解决办法

1)在vector中,解决迭代器失效的办法是在插入、删除等可能会导致迭代器失效的地方,返回新的迭代器来解决迭代器失效。

到此这篇关于c++中vector的使用和模拟实现的文章就介绍到这了,更多相关c++ vector使用内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • c++ vector模拟实现的全过程

    一.vector是什么? vector是表示可变大小数组的序列容器,它也采用连续存储空间来存储元素,因此可以采用下标对vector的元素进行访问,它的大小是动态改变的,vector使用动态分配数组来存储它的元素: 二.容器特性 1.顺序序列 顺序容器中的元素按照严格的线性顺序排序.可以通过元素在序列中的位置访问对应的元素; 2.动态数组 支持对序列中的任意元素进行快速直接访问,甚至可以通过指针进行该操作.操供了在序列末尾相对快速地添加/删除元素的操作; 3.能够感知内存分配器的 容器使用一个内存

  • C++中vector操作方式详解(多种方式)

    1. vector: 1.1 vector 说明 vector是向量类型,可以容纳许多类型的数据,因此也被称为容器 (可以理解为动态数组,是封装好了的类) 进行vector操作前应添加头文件#include <vector> 1.2 vector初始化: 方式1. //定义具有10个整型元素的向量(尖括号为元素类型名,它可以是任何合法的数据类型),不具有初值,其值不确定 vector<int>a(10); 方式2. //定义具有10个整型元素的向量,且给出的每个元素初值为1 vec

  • C++ vector类的模拟实现方法

    vector和string虽然底层都是通过顺序表来实现的,但是他们利用顺序表的方式不同,string是指定好了类型,通过使用顺序表来存储并对数据进行操作,而vector是利用了C++中的泛型模板,可以存储任何类型的数据,并且在vector中,并没有什么有效字符和容量大小的说法,底层都是通过迭代器进行操作的,迭代器底层实现也就是指针,所以说,vector是利用指针对任何顺序表进行操作的. vector属性 _start用于指向第一个有效元素 _finish用于指向最后一个有效元素的下一个位置 _e

  • c++ vector对象相关总结

    下面随笔讲解c++ vector对象. vector对象 为什么需要vector? 封装任何类型的动态数组,自动创建和删除. 数组下标越界检查. 封装的如ArrayOfPoints也提供了类似功能,但只适用于一种类型的数组. vector对象的定义 vector<元素类型> 数组对象名(数组长度); 例: vector<int> arr(5) 建立大小为5的int数组 vector对象的使用 对数组元素的引用 与普通数组具有相同形式: vector对象名 [ 下标表达式 ] vec

  • 详解C++ STL vector容器访问元素的几种方式

    学会如何创建并初始化 vector 容器之后,本节继续来学习如何获取(甚至修改)容器中存储的元素. 访问vector容器中单个元素 首先,vector 容器可以向普通数组那样访问存储的元素,甚至对指定下标处的元素进行修改,比如: #include <iostream> #include <vector> using namespace std; int main() { vector<int> values{1,2,3,4,5}; //获取容器中首个元素 cout &l

  • 详解C++ STL vector容量(capacity)和大小(size)的区别

    很多初学者分不清楚 vector 容器的容量(capacity)和大小(size)之间的区别,甚至有人认为它们表达的是一个意思.本节将对 vector 容量和大小各自的含义做一个详细的介绍. vector 容器的容量(用 capacity 表示),指的是在不分配更多内存的情况下,容器可以保存的最多元素个数:而 vector 容器的大小(用 size 表示),指的是它实际所包含的元素个数. 对于一个 vector 对象来说,通过该模板类提供的 capacity() 成员函数,可以获得当前容器的容量

  • C++ vector容器 find erase的使用操作:查找并删除指定元素

    概念:容器.迭代器.算法 STL包括容器.迭代器和算法: 容器 用于管理一些相关的数据类型.每种容器都有它的优缺点,不同的容器反映出程序设计的不同需求.容器自身可能由数组或链表实现,或者容器中的每个元素都有特殊的关键值. 迭代器 用于遍历一个数据集中的每个元素.这些数据集可能是容器或者容器的子集.迭代器的主要优点是它们为任意类型的容器提供一个小巧并且通用(注意通用很重要)的接口.例如,迭代器接口的一个操作是让它依次遍历数据集的每个元素.这个操作是依赖容器的内总部结构独立完成的.迭代器之所以有效是

  • C++ vector扩容解析noexcept应用场景

    c++11提供了关键字noexcept,用来指明某个函数无法--或不打算--抛出异常: void foo() noexcept; // a function specified as will never throw void foo2() noexcept(true); // same as foo void bar(); // a function might throw exception void bar2() noexcept(false); // same as bar 所以我们需要

  • c++中vector的使用和模拟实现

    一.接口介绍 1.插入数据 void push_back(const T& x) 在当前vector尾部插入x,如果容量不够扩大二倍. iterator insert(iterator pos, const T& x) 在POS位置插入元素x 2.容量相关 size_t capacity() 返回当前vector的容量(size+剩余容量) size_t size() 返回当前vector的元素个数 void resize(size_t n, const T& val = T())

  • 详解C++中vector的理解以及模拟实现

    目录 vector介绍 vector常见函数介绍 vector模拟实现及迭代器失效讲解 vector介绍 vector文档 1.vector是表示可变大小数组的序列容器. 2.就像数组一样,vector也采用的连续存储空间来存储元素.也就是意味着可以采用下标对vector的元素进行访问,和数组一样高效.但是又不像数组,它的大小是可以动态改变的,而且它的大小会被容器自动处理. 3.本质讲,vector使用动态分配数组来存储它的元素.当新元素插入时候,这个数组需要被重新分配大小为了增加存储空间.其做

  • C++中vector的模拟实现实例详解

    目录 vector接口总览 默认成员函数 构造函数 拷贝构造 赋值重载 析构函数 迭代器相关函数 begin和end 容量相关函数 size和capacity reserve resize empty 修改容器相关函数 push_back pop_back insert erase swap 访问容器相关函数 operator[ ] 总结 vector接口总览 namespace nzb { //模拟实现vector template<class T> class vector { publi

  • C++中priority_queue的使用与模拟实现

    目录 priority_queue的使用 priority_queue简介 priority_queue的使用 priority_queue的模拟实现 priority_queue的使用 priority_queue文档介绍 priority_queue简介 优先队列是一种容器适配器,有严格的排序标准,它的第一个元素总是它所包含的元素中最大的(或最小的). 此上下文类似于堆,在堆中可以随时插入元素,并且只能检索最大堆(或 最小堆)元素(优先队列中位于顶部的元素). 默认情况下,如果没有为特定的p

  • C++中list的使用与模拟实现

    目录 一.list的介绍以及使用 1.1 list的介绍 1.2 list的使用 1.2.1 list的构造 1.2.2 list iterator的使用 1.2.3 list capacity 1.2.4 list element access 1.2.5 list modifiers 1.2.6 list的迭代器失效 二.list的模拟实现 2.1 模拟实现list 总结 一.list的介绍以及使用 1.1 list的介绍 1.list是可以在常数范围内在任意位置进行插入和删除的序列式容器,

  • C++ 中Vector常用基本操作

    标准库vector类型是C++中使用较多的一种类模板,vector类型相当于一种动态的容器,在vector中主要有一些基本的操作,下面通过本文给大家介绍,具体内容如下所示: (1)头文件#include<vector>. (2)创建vector对象,vector<int> vec; (3)尾部插入数字:vec.push_back(a); (4)使用下标访问元素,cout<<vec[0]<<endl;记住下标是从0开始的. (5)使用迭代器访问元素. vect

  • C++中vector容器的用法

    在c++中,vector是一个十分有用的容器,下面对这个容器做一下总结. 1 基本操作 (1)头文件#include<vector>. (2)创建vector对象,vector<int> vec; (3)尾部插入数字:vec.push_back(a); (4)使用下标访问元素,cout<<vec[0]<<endl;记住下标是从0开始的. (5)使用迭代器访问元素. vector<int>::iterator it; for(it=vec.begi

  • java中vector与hashtable操作实例分享

    众所周知,java中vector与hashtable是线程安全的,主要是java对两者的操作都加上了synchronized,也就是上锁了.因此 在vector与hashtable的操作是不会出现问题.但是有一种情况:就是将一个hashtable copy到另一个hashtable时,假如使用putAll方法的花,会抛出一个 java.util.ConcurrentModificationException异常.先上代码: TestSync.java 复制代码 代码如下: public clas

  • C++中vector的用法实例解析

    本文实例展示了C++中的vector用法,分享给大家供大家参考.具体如下: 一.概述 vector是C++标准模板库中的部分内容,它是一个多功能的,能够操作多种数据结构和算法的模板类和函数库.vector是一个容器,它能够存放各种类型的对象,简单地说,vector是一个能够存放任意类型的动态数组,可以动态改变大小. 例如: // c语言风格 int myHouse[100] ; // 采用vector vector<int> vecMyHouse(100); 当如上定义后,vecMyHouse

  • C++中vector可以作为map的键值实例代码

    因为项目中需要根据状态找到一个对应的结果,就采用了map的结构,但是状态本身较为复杂,存在一个vector中.上次使用map的经验是自定义类类型作为键值必须重载<操作符,因为map的快速查找是基于红黑树的构建,因而键值必须能相互之间比较.所以担心vector作为类类型的键值会引发一些错误,就写了一个例子测试.结果证明vector可以直接作为map的键值使用. #include<iostream> #include<string> #include<vector>

随机推荐