【C++】vector的使用和模拟实现

文章目录

  • 一、vector 定义
  • 二、vector使用
    • 1. 初始化
    • 2. 插入
    • 3. 遍历
    • 4. 重新分配容量
    • 5. 查找
    • 6. 清除
  • 三、vector模拟实现
    • 参数
    • 构造函数
    • 析构函数
    • 拷贝构造
    • 遍历[]
    • 始末位置/容量/大小
    • 扩容
    • 插入push_back
    • 插入insert
    • 删除erase

一、vector 定义

vector是表示可变大小数组的序列容器

本质其实就是一个动态的顺序表

【C++】vector的使用和模拟实现_第1张图片


二、vector使用

1. 初始化

#define _CRT_SECURE_NO_WARNINGS
#include 
#include 
#include 
using namespace std;

void test1()
{
	vector<int> v1;
	vector<int> v2(10, 1);//初始化,10个1
	vector<int> v3(v2.begin(), v2.end());//迭代器范围初始化
	vector<int> v4(v3);//拷贝构造
	string s("hello");
	vector<char> v5(s.begin(), s.end());//范围初始化模板可以用string类

}

这里不会把\0拷贝过去

【C++】vector的使用和模拟实现_第2张图片


2. 插入

void test2()
{
	vector<int> v1;
	v1.push_back(1);
	v1.push_back(1);
	v1.push_back(1);
	v1.push_back(1);
	v1.push_back(1);//尾插

	v1.pop_back();//尾删
	//中间插入/删除
	v1.erase(v1.begin() + 2);
	v1.insert(v1.end(), 1);
}

3. 遍历

注意这里的end

【C++】vector的使用和模拟实现_第3张图片

//测试遍历
for (size_t i = 0; i < v1.size(); i++)
{
	cout << v1[i];
}
cout << endl;

//迭代器
vector<int>::iterator it = v1.begin();

while (it != v1.end())
{
	cout << *it;
	it++;
}
cout << endl;

//范围for
for (auto e : v1)
{
	cout << e;
}
cout << endl;

测试:

【C++】vector的使用和模拟实现_第4张图片


4. 重新分配容量

void test3()
{
	vector<int> v1;
	v1.push_back(1);
	v1.push_back(1);
	v1.push_back(1);
	v1.push_back(1);
	v1.push_back(1);//尾插

	v1.reserve(10);
	v1.resize(10);
    v1.assign(10, 5);//重新分配10个5数值
}

reserve

【C++】vector的使用和模拟实现_第5张图片

resize

【C++】vector的使用和模拟实现_第6张图片


5. 查找

vector不提供类似string那样的find的功能

std提供了algorithm算法库

【C++】vector的使用和模拟实现_第7张图片

void test4()
{
	vector<int> v1;
	v1.push_back(1);
	v1.push_back(2);
	v1.push_back(3);
	v1.push_back(4);

	vector<int>::iterator ret = find(v1.begin(), v1.end(), 2);
	cout << *ret;
}

测试:

【C++】vector的使用和模拟实现_第8张图片

优化:

void test4()
{
	vector<int> v1;
	v1.push_back(1);
	v1.push_back(2);
	v1.push_back(3);
	v1.push_back(4);

	vector<int>::iterator ret = find(v1.begin(), v1.end(), 2);

	if (ret != v1.end())//没找到返回end
	{
		cout << *ret;
	}
}

6. 清除

清除数据但不清除空间

v1.clear();

三、vector模拟实现

参数

#pragma once
#include 
#include 
using namespace std;

namespace wyj
{
	template<class T>
	class vector
	{
		typedef T* iterator;
		typedef const T* const_iterator;
	public:
    private:
        iterator _start;
		iterator _finish;
		iterator _endofstorage;
    };
}

构造函数

//构造函数
vector()
	:_start(nullptr),
	_finish(nullptr),
	_endofstorage(nullptr)
{}


析构函数

//析构函数
~vector()
{
	//如果是空指针直接进行delete会报错
	if (_start)
	{
		delete[] _start;
		_start = _finish = _endofstorage;
	}
}

拷贝构造

//拷贝构造
vector(const vector<T>& v)
{
	_start = new T[v.capacity()];
	_finish = _start + v.size();
	_endofstorage = _start + v.capacity();
	memcpy(_start, v._start, v.capacity());
    return *this;
}

优化:

使用自己的构造函数【在string那节有相似的方法

【C++】vector的使用和模拟实现_第9张图片

如果要实现,有以下问题,我想使用它自己的构造函数,构造新的vector,然后把成员变量给新的

//这里不能直接写
//vector(T* start)
//{   
//}
//因为要计算start的size长度,没有任何具体的方法,数组有数组的方法,字符串有字符串的方法
vector()
    :_start(nullptr),
	_finish(nullptr),
	_endofstorage(nullptr)
{}

vector(const vector<T>& v)
{
    //这里如何使用自己的东西去拷贝构造是问题
    vector<T> tmp();
}

vector构造函数中有

【C++】vector的使用和模拟实现_第10张图片

//构造函数另一个版本,构成函数重载
//这样不仅可以用vector迭代器,还可以用别的类型string的迭代器
//比如vector s1和string s2,可以用s1(s2.begin(), s2.end())
template <class InputIterator>
vector(InputIterator first, InputIterator last)
	:_start(nullptr),
	_finish(nullptr),
	_endofstorage(nullptr)
{
	while (first != last)
	{
		push_back(*first);
		first++;
	}
}

拷贝构造和operator=

这里为什么不直接使用库函数的swap?
库函数的swap是一个深拷贝,将先创建一个新的vector,然后再相等,最后交换(深拷贝,效率低,我们不需要那么精准的拷贝),我们只需要成员变量的交换

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

//拷贝构造函数
vector(const vector<T>& v)
	:_start(nullptr),
	_finish(nullptr),
	_endofstorage(nullptr)
{
	//这里使用类自己的构造函数
	vector<T> tmp(v.begin(), v.end());
	//这里不能直接相等,因为函数结束tmp会delete,必须把tmp变为nullptr
	swap(tmp);
}

vector<T>& operator=(const vector<T> v)//这里直接用拷贝构造函数
{
	swap(v);
	return *this;
}

测试:

void test3()
{
	vector<int> v;
	v.push_back(1);
	v.push_back(1);
	v.push_back(1);

	vector<int> v1;
	v1 = v;

	for (auto e : v1)
	{
		cout << e;
	}
	cout << endl;

}

【C++】vector的使用和模拟实现_第11张图片


遍历[]

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

}

始末位置/容量/大小

const_iterator begin()const
{
	return _start;
}

const_iterator end()const
{
	return _finish;
}

iterator begin()
{
	return _start;
}

iterator end()
{
	return _finish;
}

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

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

扩容

//关于扩容
void reserve(size_t n)
{
	if (n > capacity())
	{
		//这里要提前保存,不然size = finish - start 如果start已经变了,再相减就不一样了
		size_t ret = size();
		T* tmp = new T[n];

		//如果是空直接给,不是空拷贝
		if (_start != nullptr)
		{
			memcpy(tmp, _start, sizeof(T) * size());
			delete[] _start;
		}

		_start = tmp;
		_finish = _start + ret;
		_endofstorage = _start + n;
	}

}

void resize(size_t n, const T& val = T())//没给数值默认初始化为T类型的
{
	if (n < size())
	{
		_finish = _start + n;
	}
	else
	{
		if (n > capacity())
		{
			reserve(n);
		}

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

}

测试:

//测试resverse
void test2()
{
	vector<int> v;
	v.push_back(1);
	v.push_back(1);
	v.push_back(1);

	v.reserve(6);

	for (auto e : v)
	{
		cout << e;
	}
	cout << endl;
	v.resize(7);

	for (auto e : v)
	{
		cout << e;
	}
	cout << endl;

	v.resize(2);
	for (auto e : v)
	{
		cout << e;
	}
	cout << endl;

}

【C++】vector的使用和模拟实现_第12张图片


插入push_back

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

	*_finish = x;
	_finish++;
}

测试

//测试插入和遍历
void test1()
{
	vector<int> v;
	v.push_back(1);
	v.push_back(1);
	v.push_back(1);
	v.push_back(1);

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

	cout << endl;
}

【C++】vector的使用和模拟实现_第13张图片


插入insert

void insert(iterator pos, const T& x)
{
	assert(pos >= _start && pos <= _finish);
	//相等
	if (_finish == _endofstorage)
	{
		reserve(capacity() == 0 ? 4 : 2 * capacity());
	}

	iterator end = _finish - 1;

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

测试:

【C++】vector的使用和模拟实现_第14张图片


问题:如果扩容之后,pos指向的是释放过的空间,野指针,迭代器失效

【C++】vector的使用和模拟实现_第15张图片


修改:

void insert(iterator pos, const T& x)
{
	assert(pos >= _start && pos <= _finish);
	//相等
	if (_finish == _endofstorage)
	{
        //提前保存距离
        size_t len = pos - _start;
		reserve(capacity() == 0 ? 4 : 2 * capacity());
        pos = _start + len;
	}

	iterator end = _finish - 1;

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

删除erase

【C++】vector的使用和模拟实现_第16张图片

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

	_finish--;

	return pos;
}

测试:

【C++】vector的使用和模拟实现_第17张图片


你可能感兴趣的:(C++,programing,langua,vector,STL,C++)