vector
vector介绍
vector 是 C++ 标准模板库(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
n<=
capacity直接进行移动
_finishn>
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;
};
}