学习笔记—C++—vector

vector

vector介绍

vectorC++ 标准模板库(STL)中的一个动态数组容器,也是C++的顺序表,它提供了动态大小调整和高效的随机访问功能。vector 的元素在内存中是连续存储的,这意味着可以通过指针或索引高效地访问元素。vector 自动管理其内部使用的内存,不需要手动分配和释放,支持常见容器操作,如插入、删除、遍历等.

String和vector区别

String结尾有\0;vector要储存其他类型所以没有\0

String主要用来存储char类型;vector主要用来存储除char的其他类型

vector常见接口

构造函数

存储结构

结构上使用命名空间wu进行封装,防止与库冲突,使用class封装成为对象vector

这样typedef的一点是和STL保持一致

写vector写成类模板,可以支持存贮多种类型数据
_start表示数据存储的开始地址
_finish表示数据存贮的的下一个地址
_endofstorage表示数据当前开辟的最大空间的地址

cpp 复制代码
namespace wu
{
    template<class T>
    class vector
    {
    public:
        typedef T* iterator;
        typedef const T* const_iterator;
    private:

        iterator _start;
        iterator _finish;
        iterator _endofstorage;
    };
}
默认构造函数
初始化

初始化指针都为空

cpp 复制代码
vector()
    :_start(nullptr)
        , _finish(nullptr)
        , _endofstorage(nullptr)
    {}

模版的定义,进行初始化

cpp 复制代码
//类模版的成员函数,也可以是一个函数模版
template<class InputIterator>
vector(InputIterator first, InputIterator last)
{
	while (first != last)
	{
		push_back(*first);
		++first;
	}
}
拷贝构造函数

利用一个对象初始化另外一个对象传引用

new出和传递的对象一样大小的空间,在string类中我们利用了mencpy进行拷贝,在vector中不采用mencpy

mencpy拷贝只能进行内置类型的浅拷贝,不能进行自定义类型的深拷贝

在这里面进行依次赋值,或者push_back

最后进行_finish和_endofstorage的初始化

cpp 复制代码
vector(const vector<T>& v)
{

    _start = new T[v.capacity()];

    for (size_t i = 0; i < v.size(); i++)
    {
        _start[i] = v._start[i];
    }

    _finish = _start + v.size();
    _endofstorage = _start + v.capacity();

}
赋值运算符重载

operator=的参数中是值传递,是实参的拷贝,这里面利用这个特性进数据的交换

返回this指针就是赋值的内容了

cpp 复制代码
void swap(vector<T>& tmp)
{
	std::swap(_start, tmp._start);
	std::swap(_finish, tmp._finish);
	std::swap(_endofstorage, tmp._endofstorage);
}

vector<T>& operator=(vector<T> v)
{
	swap(v);
	return *this;
}
析构函数

判断_start是否为空为空,避免再次析构

cpp 复制代码
~vector()
{
    if (_start)
    {

        delete[] _start;
        _start = _finish = _endofstorage = nullptr;
    }

}

迭代器(iterator)

本质是指针

cpp 复制代码
const_iterator cbegin()
{
    return _finish;
}

const_iterator cend() const
{
    return _start;
}
iterator begin()
{
    return _start;
}
iterator end()
{
    return _finish;
}
const_iterator begin()const
{
    return _start;
}
const_iterator end()const
{
    return _finish;

容量(capacity)

capacity
cpp 复制代码
size_t capacity() const
{
	return _endofstorage - _start;
}
size
cpp 复制代码
size_t size() const
{
	return _finish - _start;
}
empty
cpp 复制代码
bool empty()
{
	return _start == _finish;
}
resize
  1. n<=capacity

    直接进行移动_finish

  2. n>capacity

    进行容量的检查和扩容,依次赋值val

cpp 复制代码
void resize(size_t n, T val = T())
{
	if (n <= size())
	{
		_finish = _start + n;
	}
	else
	{
		reserve(n);

		while (_finish < _start + n)
		{
			*_finish = val;
			++_finish;
		}
	}
}
reserve

开始判断需要扩容的大小是否大于capacity,以避免重复扩容效率低下

在开始时候记录原始空间的大小,是为了避免迭代器失效

进行空间的扩容,会将原来的空间析构,原始的计算空间大小已经已释放,指向的_start _finish _endofstorage已经失效

这里还是采用在这里面进行依次赋值,或者push_back

更新_start _finish _endofstorage

cpp 复制代码
void reserve(size_t n)
{
	if (n > capacity())
	{
		size_t oldSize = size();
		T* tmp = new T[n];
		if (_start)
		{
			//memcpy(tmp, _start, sizeof(T) * oldSize);
			for (size_t i = 0; i < oldSize; i++)
			{
				tmp[i] = _start[i];
			}
			delete[]_start;
		}
				
		_start = tmp;
		_finish = _start + oldSize;
		_endofstorage = _start + n;

	}
}

修改(modify)modify

push_back

首先进行容量的检查

直接将_finsih位置解引用赋值, ++_finsih

cpp 复制代码
void push_back(const T& x)
{
    if (_finish == _end_of_storage)
    {
        size_t newcapacity = capacity() == 0 ? 4 : capacity() * 2;
        reserve(newcapacity);
    }

    *_finish = x;
    ++_finish;
    //insert(_finish, x);
}
pop_back
cpp 复制代码
void pop_back()
{
	assert(!empty());
	_finish--;
    //erase(end()-1);
}
insert

进行断言,防止pos越界访问

判断空间的大小_finish == _endofstorage
size_t len = pos - _start用step记录,距离 _start距离,扩容的时候将原空间释放,pos将无法访问,扩容完成后进行pos的恢复

将pos位置的数据依次进行移动、

插入pos位置的值,修改_finish

为了避免迭代器失效,返回现在的位置pos

cpp 复制代码
iterator insert(iterator pos, const T& x)
{
	assert(pos >= _start && pos <= _finish);

	if (_finish == _endofstorage)
	{
		size_t len = pos - _start;
		reserve(capacity() == 0 ? 4 : capacity() * 2);
		pos = _start + len;
	}

	iterator i = _finish - 1;
	while (i >= pos)
	{
		*(i + 1) = *i;
		--i;
	}
	*pos = x;
	++_finish;

	return pos;
}
erase

进行断言,防止pos越界访问

pos后面的元素向前面移动,进行覆盖

为了避免迭代器失效,返回现在的位置pos

cpp 复制代码
iterator erase(iterator pos)
{
	assert(pos >= _start);
	assert(pos < _finish);
	iterator i = pos + 1;
	while (i < _finish)
	{
		*(i - 1) = *i;
		++i;
	}
	_finish--;

	return pos;
}
swap
cpp 复制代码
void swap(vector<T>& tmp)
{
	std::swap(_start, tmp._start);
	std::swap(_finish, tmp._finish);
	std::swap(_endofstorage, tmp._endofstorage);
}
operator[]

实现const非const两种,只读和可读可改

充分利用字符串特性可以进行下标的访问

cpp 复制代码
T& operator[](size_t i)
{
    assert(i >= 0 && i < size());

    return _start[i];
}

const T& operator[](size_t i)const
{
    assert(i >= 0 && i < size());

    return _start[i];
}

源码

cpp 复制代码
#pragma once
#include<assert.h>
#include<iostream>

using namespace std;


namespace wu
{
	template<class T>
	class vector
	{
	public:
		typedef T* iterator;
		typedef const T* const_iterator;
		iterator begin()
		{
			return _start;
		}
		iterator end()
		{
			return _finish;
		}

		const_iterator begin() const
		{
			return _start;
		}
		const_iterator end() const
		{
			return _finish;
		}

		vector()
		{}

		//类模版的成员函数,也可以是一个函数模版
		template<class InputIterator>
		vector(InputIterator first, InputIterator last)
		{
			while (first != last)
			{
				push_back(*first);
				++first;
			}
		}

		vector(size_t n, const T& val = T())
		{
			reserve(n);
			for (size_t i = 0; i < n; i++)
			{
				push_back(val);
			}
		}

		vector(int n, const T& val = T())
		{
			reserve(n);
			for (int i = 0; i < n; i++)
			{
				push_back(val);
			}
		}

		vector(initializer_list<T> il)
		{
			reserve(il.size());
			for (auto& e : il)
			{
				push_back(e);
			}
		}

		vector(const vector<T>& v)
		{
			reserve(v.capacity());
			for (auto& e : v)
			{
				push_back(e);
			}
		}

		void swap(vector<T>& tmp)
		{
			std::swap(_start, tmp._start);
			std::swap(_finish, tmp._finish);
			std::swap(_endofstorage, tmp._endofstorage);
		}

		vector<T>& operator=(vector<T> v)
		{
			swap(v);
			return *this;
		}


		~vector()
		{
			if (_start)
			{
				delete[]_start;
				_start = _finish = _endofstorage = nullptr;
			}
		}

		T& operator[](size_t i)
		{
			assert(i < size());

			return _start[i];
		}

		size_t size() const
		{
			return _finish - _start;
		}

		size_t capacity() const
		{
			return _endofstorage - _start;
		}

		void reserve(size_t n)
		{
			if (n > capacity())
			{
				size_t oldSize = size();
				T* tmp = new T[n];
				if (_start)
				{
					//memcpy(tmp, _start, sizeof(T) * oldSize);
					for (size_t i = 0; i < oldSize; i++)
					{
						tmp[i] = _start[i];
					}
					delete[]_start;
				}
				
				_start = tmp;
				_finish = _start + oldSize;
				_endofstorage = _start + n;

			}
		}

		void resize(size_t n, T val = T())
		{
			if (n <= size())
			{
				_finish = _start + n;
			}
			else
			{
				reserve(n);

				while (_finish < _start + n)
				{
					*_finish = val;
					++_finish;
				}
			}
		}

		//void reserve(size_t n)
		//{
		//	if (n > capacity())
		//	{
		//		T* tmp = new T[n];
		//		memcpy(tmp, _start, sizeof(T) * size());
		//		delete[]_start;

		//		_finish = tmp + size();
		//		_start = tmp;

		//		_endofstorage = _start + n;

		//	}
		//}

		void push_back(const T& x)
		{
			//if (_finish == _endofstorage)
			//{
			//	reserve(capacity() == 0 ? 4 : capacity() * 2);
			//}
			//*_finish = x;
			//++_finish;

			insert(_finish, x);
		}

		bool empty()
		{
			return _start == _finish;
		}

		void pop_back()
		{
			assert(!empty());
			_finish--;
		}

		//迭代器失效,本质因为一些原因,迭代器不可用
		iterator insert(iterator pos, const T& x)
		{
			assert(pos >= _start && pos <= _finish);

			if (_finish == _endofstorage)
			{
				size_t len = pos - _start;
				reserve(capacity() == 0 ? 4 : capacity() * 2);
				pos = _start + len;
			}

			iterator i = _finish - 1;
			while (i >= pos)
			{
				*(i + 1) = *i;
				--i;
			}
			*pos = x;
			++_finish;

			return pos;
		}

		iterator erase(iterator pos)
		{
			assert(pos >= _start);
			assert(pos < _finish);
			iterator i = pos + 1;
			while (i < _finish)
			{
				*(i - 1) = *i;
				++i;
			}
			_finish--;

			return pos;
		}


	private:
		iterator _start = nullptr;
		iterator _finish = nullptr;
		iterator _endofstorage = nullptr;
	};
}
相关推荐
一匹电信狗41 分钟前
【LeetCode】栈和队列进阶题目
c++·算法·leetcode·职场和发展·stl·栈和队列
Bin二叉42 分钟前
南京大学cpp复习——第二部分(继承)
开发语言·c++·笔记·学习
代码游侠44 分钟前
数据结构——线性表
linux·c语言·数据结构·学习·算法
人邮异步社区1 小时前
完全没接触过AI/NLP,如何系统学习大模型?
人工智能·学习·自然语言处理·大模型
。TAT。1 小时前
进程间通信-对匿名管道的学习
linux·学习
empti_1 小时前
《大规模 3D 城市布局的语义与结构引导可控生成》翻译
论文阅读·笔记
QiZhang | UESTC1 小时前
学习日记day37
学习
YJlio1 小时前
SDelete 学习笔记(9.9):安全擦除原理、SSD 场景与企业合规实战
笔记·学习·安全
弘毅 失败的 mian1 小时前
Linux 基本工具详解
linux·运维·服务器·经验分享·笔记
摇滚侠1 小时前
零基础小白自学 Git_Github 教程,DeskTop 进阶操作,笔记12
笔记·git·github