C++Vector容器常用函数接口详解

目录
  • 一、基础框架
  • 二、迭代器实现
  • 三、size capacity resize reserve
  • 四、insert,erase
  • 五、pop_back,push_back
  • 六、operator[]
  • 七、构造函数 析构函数 赋值重载

一、基础框架

template<class T>
class vector
{
public:
	typedef T* iterator;
	typedef const T* const_iterator;
private:
	iterator _start;//指向第一个元素
	iterator _finish;//指向最后一个元素的下一个位置
	iterator _endofstoage;//容量
};

二、迭代器实现

const_iterator begin() const
{
	return _str;
}
const_iterator end() const
{
	return _str + _size;
}
iterator begin()
{
	return _str;
}
iterator end()
{
	return _str + _size;
}

三、size capacity resize reserve

		size_t size() const
		{
			return _finish - _start;
		}
		size_t capacity() const
		{
			return _endofstoage - _start;
		}
		void reserve(size_t n)
		{
			size_t sz = size();
			if (n > capacity())
			{
				T* tmp = new T[n];
				//T* tmp = (T*)malloc(sizeof(T)*n);
				if (_start)
				{
					//memcpy(tmp, _start, size()*sizeof(T));
					for (size_t i = 0; i < size(); ++i)
					{
						tmp[i] = _start[i];
					}
					delete[] _start;
				}
				_start = tmp;
			}
			_finish = _start + sz;
			_endofstoage = _start + n;
		}
		//void resize(size_t n, const T& val = T())
		void resize(size_t n, T val = T())//T类型的匿名对象做缺省参数,调用T的默认构造函数
		{
			if (n > capacity())
			{
				reserve(n);
			}
			if (n > size())
			{
				while (_finish < _start + n)
				{
					*_finish = val;
					++_finish;
				}
			}
			else
			{
				_finish = _start + n;
			}
		}

注意点:在reservr函数中,在拷贝的时候,不可以简单的通过memcpy函数来浅拷贝,因为当T是涉及到深浅拷贝的类型时,使用memcpy会存在深浅拷贝释放内存空间的问题。

四、insert,erase

		iterator insert(iterator pos, const T& x)
		{
			// 检查参数
			assert(pos >= _start && pos <= _finish);
			// 扩容
			// 扩容以后pos就失效了,需要更新一下
			if (_finish == _endofstoage)
			{
				size_t n = pos - _start;
				size_t newCapacity = capacity() == 0 ? 4 : capacity() * 2;
				reserve(newCapacity);
				pos = _start + n;
			}
			// 挪动数据
			iterator end = _finish - 1;
			while (end >= pos)
			{
				*(end + 1) = *end;
				--end;
			}
			*pos = x;
			++_finish;
			return pos;
		}
		iterator erase(iterator pos)
		{
			assert(pos >= _start && pos < _finish);
			iterator it = pos + 1;
			while (it != _finish)
			{
				*(it - 1) = *it;
				++it;
			}
			--_finish;
			return pos;
		}

注意点:在insert函数中,如果需要扩容的话,注意扩容前后pos位置的更新,其实STL库中也进行了这样的更新,不更新的话位置就失效了 。

五、pop_back,push_back

		void push_back(const T& x)
		{
			/*if (_finish == _endofstoage)
			{
				size_t newcapacity = capacity() == 0 ? 4 : 2 * capacity();
				reserve(newcapacity);
			}
			*_finish = x;
			_finish++;*/
			insert(end(), x);
		}
		void pop_back()
		{
			erase(end() - 1);//复用
		}

注意点:可以直接复用insert和erase函数。

六、operator[]

		T& operator[](size_t pos)
		{
			assert(pos < size());
			return *(_start + pos);
		}
		const T& operator[](size_t pos) const
		{
			assert(pos < size());
			return *(_start + pos);
		}

注意点:分别针对常对象和普通对象。

七、构造函数 析构函数 赋值重载

		vector()
			:_start(nullptr)
			, _finish(nullptr)
			, _endofstoage(nullptr)
		{}
		//为什么要有这个
		//是为了拷贝构造的现代写法时有一个可用的有参构造可以用
		template <class InputIterator>
		vector(InputIterator first, InputIterator last)
			: _start(nullptr)
			, _finish(nullptr)
			, _endofstoage(nullptr)
		{
			while (first != last)
			{
				push_back(*first);
				++first;
			}
		}
		//n个val调用的构造函数
		vector(size_t n, const T& val = T())//用一个匿名对象做缺省参数
			: _start(nullptr)
			, _finish(nullptr)
			, _endofstoage(nullptr)
		{
			reserve(n);
			for (size_t i = 0; i < n; ++i)
			{
				push_back(val);
			}
		}
		vector(int n, const T& val = T())
			: _start(nullptr)
			, _finish(nullptr)
			, _endofstoage(nullptr)
		{
			reserve(n);
			for (int i = 0; i < n; ++i)
			{
				push_back(val);
			}
		}
		void swap(vector<T>& v)
		{
			std::swap(_start, v._start);
			std::swap(_finish, v._finish);
			std::swap(_endofstoage, v._endofstoage);
		}
		//vector(const vector& v);
		vector(const vector<T>& v)
			: _start(nullptr)
			, _finish(nullptr)
			, _endofstoage(nullptr)
		{
			vector<T> tmp(v.begin(), v.end());
			swap(tmp);
		}
		//vector& operator=(vector v)
		vector<T>& operator=(vector<T> v)
		{
			swap(v);
			return *this;
		}
		// 资源管理
		~vector()
		{
			if (_start)
			{
				delete[] _start;
				_start = _finish = _endofstoage = nullptr;
			}
		}

注意点1: 赋值重载的形参列表利用传值传参,调用了拷贝构造完成了深拷贝,直接交换!

注意点2:注意这种拷贝构造和赋值重载的现代写法(请人干活,窃取果实),但必须得有对应的有参构造!

到此这篇关于C++Vector容器常用函数接口详解的文章就介绍到这了,更多相关C++ Vector容器内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • C++超详细讲解模拟实现vector

    目录 1. 模拟实现vector 2. vector常用接口 2.1 reserve 2.2 resize 2.3 push_back 2.4 pop_back() 2.5 insert 2.6 erase 2.7 构造函数的匹配问题 3. 更深层次的深浅拷贝问题 1. 模拟实现vector 我们模拟实现是为了加深对这个容器的理解,不是为了造更好的轮子. 快速搭一个vector的架子 // vector.h #pragma once #include <assert.h> // 模拟实现 --

  • C++类模板实战之vector容器的实现

    目录 案例要求 完成步骤 1.封装数组类属性并完成有参构造以及析构函数 2.提供对应的深拷贝构造函数防止调用析构时出错 3.重载类内的赋值运算符防止浅拷贝问题出现 4.提供尾部插入和删除的方法 5.重载[]得到数组中对应下标的数据信息 6.提供get方法获取当前数组容量及大小 7.提供打印函数测试基本数据类型和自定义数据类型的存储 案例要求 可以对内置数据类型以及自定义数据类型的数据进行存储 将数组中的数据存储到堆区 构造函数中可以传入数组的容量 提供对应的拷贝构造函数以及operator=防止

  • C++STL之vector模板类详解

    目录 前言 vector模板类 创建vector对象,遍历元素 迭代器 容器的基本方法 STL函数,sort 总结 前言 STL标准模板库是C++中非常有用的功能库.本篇从vector容器开始学习STL. vector模板类 创建vector对象,遍历元素 vector模板类在头文件vector中,用于存储数组,并采用动态内存分配. 创建一个vector对象并初始化长度,通过[]运算符访问元素: #include <vector> using namespace std; int main()

  • 详解C++中的vector容器及用迭代器访问vector的方法

    vector vector是相同类型对象的集合.集合中的每个对象有个对应的索引.vector常被称为容器(container). 为了使用vector,需要: #include <vector> using std::vector; vector是一个类模版(class template).C++有函数模版和类模版.模版本身不是函数或类,必须通过指定 类型让编译器去实例化(instantiation)它.比如vector<int> ivec. vector是模版,不是类型.从vec

  • C++ vector的简单实现

    目录 向量 成员函数 cpp 总结 向量 向量是序列容器,表示可以更改大小的数组. 就像数组一样,向量对其元素使用连续的存储位置,这意味着也可以使用指向其元素的常规指针上的偏移量来访问其元素,并且与数组一样高效.但与数组不同的是,它们的大小可以动态变化,它们的存储由容器自动处理. 在内部,向量使用动态分配的数组来存储其元素.可能需要重新分配此数组,以便在插入新元素时增加大小,这意味着分配新数组并将所有元素移动到该数组.就处理时间而言,这是一项相对昂贵的任务,因此,每次将元素添加到容器时,向量都不

  • C++ Vector迭代器失效问题的解决方法

    目录 一.迭代器失效 二.可能引起的迭代器失效的操作 2.1.野指针引起迭代器失效 2.2.迭代器指向的位置意义改变 2.3.总结 一.迭代器失效 主要作用就是让算法能够不用关心底层数据结构,其底层实际就是一个指针,或者是对指针进行了封装.比如:vector的迭代器就是原生态指针T*.因此迭代器失效,实际就是迭代器底层对应指针所指向的空间被销毁了,而使用一块已经被释放的空间,造成的后果是程序崩溃(即如果继续使用已经失效的迭代器,程序可能会崩溃). 二.可能引起的迭代器失效的操作 2.1.野指针引

  • C++示例讲解vector容器

    目录 vector基本概念 创建 vector 的各种方法 vector容器的构造 vector赋值操作 vector容量和大小 vector容器插入和删除 vector数据存取 vector互换容器 vector基本概念 功能: vector数据结构和数组非常相似,也称为单端数组 vector与普通数组区别: 不同之处在于数组是静态空间,而vector可以动态扩展 动态扩展: 并不是在原空间之后继续接新空间,而是找更大的内存空间,然后将元数据拷贝新空间,释放原空间 创建 vector 的各种方

  • C++中vector迭代器失效问题详解

    目录 问题: (1)删除vector中所有的偶数 (2)vector容器插入元素问题 迭代器失效原因 解决: 总结 问题: (1)删除vector中所有的偶数 #include <iostream> #include <vector> using namespace std; int main() { vector<int> vec; for (int i = 0; i < 10; ++i) { vec.push_back(i); } //把vec容器中的所有偶数

  • C++ STL中vector容器的使用

    目录 一.vector (1)区分size()和capacity() (2)迭代器失效 (3)区分const_iterator和constiterator (4)区分reserve()和resize() (5)push_back和emplace (6)关于原位构造(定位new+完美转发) 总结 一.vector (1)区分size()和capacity() size():返回容纳的元素个数 capacity():返回当前分配存储的容量 (2)迭代器失效 (3)区分const_iterator和c

  • C++Vector容器常用函数接口详解

    目录 一.基础框架 二.迭代器实现 三.size capacity resize reserve 四.insert,erase 五.pop_back,push_back 六.operator[] 七.构造函数 析构函数 赋值重载 一.基础框架 template<class T> class vector { public: typedef T* iterator; typedef const T* const_iterator; private: iterator _start;//指向第一个

  • C++List容器常用函数接口刨析

    目录 一.基本结构 二.list的迭代器的构造 三.迭代器的实现 四.insert,erase 五.push_back,push_front,pop_back,pop_front 六.构造函数与赋值重载 七.析构与清空 一.基本结构 由源代码可知,list容器是有一个带头双向循环链表实现,所以我们模拟实现也需要实现一个带头双向循环链表的数据结构. template<class T> struct list_node { list_node<T>* _next; list_node&

  • calendar在python3时间中常用函数举例详解

    想要在python中写代码游刃有余,没有函数的支持是万万不行的.很多小伙伴反映,最近函数的应用知识不够了,所以小编挑选了python3时间中的函数,希望可以帮助大家在处理日历方面更加的迅速.其他更多的函数,大家也可以自行去搜集一点资料学习,小编就讲几个最简单的吧. 1.firstweekday() firstweekday(): 返回当前每周起始日期值.默认情况下,首次载入calendar模块时返回0,即星期一 import calendar # 0 print(calendar.firstwe

  • SQLServer之常用函数总结详解

    SQLServer中的常用函数 字符串函数 len() 计算字符串的长度 select LEN(name) from test1 --计算name的长度 大小写转换 lower() upper() select lower('STUDENT !') select upper('student !') 去空 ltrim() 字符串左侧的空格去掉 ,rtrim()字符串右侧的空格去掉 declare @str varchar(100) = ' a a a ' select ltrim(@str) s

  • Python列表常用函数使用详解

    目录 介绍  append() extend() insert() pop() remove() 介绍  append() 语法 list.append( element ) 参数 element:任何类型的元素 列表「末尾」添加元素 name_list = ['zhangsan', 'lisi', 'wangwu'] name_list.append('zhaoliu') print(name_list) 输出: ['zhangsan', 'lisi', 'wangwu', 'zhaoliu'

  • Python数据分析之NumPy常用函数使用详解

    目录 文件读入 1.保存或创建新文件 2.读取csv文件的函数loadtxt 3.常见的函数 4.股票的收益率等 5.对数收益与波动率 6.日期分析 总结 本篇我们将以分析历史股价为例,介绍怎样从文件中载入数据,以及怎样使用NumPy的基本数学和统计分析函数.学习读写文件的方法,并尝试函数式编程和NumPy线性代数运算,来学习NumPy的常用函数. 文件读入 读写文件是数据分析的一项基本技能 CSV(Comma-Separated Value,逗号分隔值)格式是一种常见的文件格式.通常,数据库的

  • Python asyncio常用函数使用详解

    目录 协程的定义 协程的运行 多个协程运行 关于loop.close() 回调 事件循环 协程的定义 需要使用 async def 语句 协程可以做哪些事: 1.等待一个future结果 2.等待另一个协程(产生一个结果或引发一个异常) 3.产生一个结果给正在等它的协程 4.引发一个异常给正在等它的协程 协程的运行 调用协程函数,协程不会开始运行,只是返回一个协程对象 要让协程对象运行有两种方式: 1.在另一个已经运行的协程中用await等待它 2.通过ensure_future函数计划它的执行

  • JavaScript 常用函数库详解

    为此,收集了自己平时常用到一些JavaScript函数,它们在其它的JS库也常见,现在整理并附上注释,方便查阅,希望对大家有所帮助.注:假设以下所有函数都放在一个CC对象中,方便引用. 复制代码 代码如下: //这个方法相信是最常用的了, //它虽然没有选择器那么强大,但也有个小增强版,可查指定结点下ID所在的子元素 function $(id, p) { //id是否是字符串,还是一个HTML结点 var iss = id instanceof String || typeof id == "

  • Python中常用的高阶函数实例详解

    前言 高阶函数指的是能接收函数作为参数的函数或类:python中有一些内置的高阶函数,在某些场合使用可以提高代码的效率. lambda 当在使用一些函数的时候,我们不需要显式定义函数名称,直接传入lambda匿名函数即可.lambda匿名函数通常和其他函数搭配使用. 比如可以直接使用如下的lambda表达式计算当x=3时,y = x * 3 + 5的函数值. In [1]: (lambda x: x * 3 + 5)(3) Out[1]: 14 map map函数将一个函数和序列/迭代器(可以传

  • Java图形化界面设计之容器(JFrame)详解

    Java图形化界面设计--容器(JFrame) 程序是为了方便用户使用的,因此实现图形化界面的程序编写是所有编程语言发展的必然趋势,在命令提示符下运行的程序可以让我们了解java程序的基本知识体系结构,现在就进入java图形化界面编程. 一.Java基本类(JFC) Java基本类("JavaFoundationClasses",JFC),由一些软件包组成.这些软件包主要包括下面一些应用程序接口(API): ·抽象窗口工具集(AWT)(1.1及以上版本). ·Swing构件. ·Jav

随机推荐