C++ vector的模拟实现
一 vector的大致框架
1.1 框架
?vector的成员变量不再是我们熟悉的size,capacity,而是变成了功能一致的三个指针:_start,_finish,_endofstorage,三个指针的作用如下:
同时,因为其本身指针的特性,其迭代器也是返回其内部的指针就可以了,因此我们可以直接定义迭代器。
?大致框架如下:
?
namespace My
{
template<class T>
class vector
{
public:
typedef T* iterator;
typedef const T* const_iterator;
private:
iterator _start;
iterator _finish;
iterator _endofstorage;
};
}
1.2 默认构造函数?
?实际上,我们可以在底层初始化给三个指针都赋值为nullptr,这样默认构造就可以什么都不敢,并且在初始化时就全都赋值为nullptr,可以使代码更加简练。
代码如下:
?
//构造函数
vector() {
}
private:
iterator _start = nullptr;
iterator _finish = nullptr;
iterator _endofstorage = nullptr;
1.3 析构函数
delete掉空间,将三个指针再次赋值为nullptr即可。
?
//析构
~vector() {
delete[] _start; //注意一定要加[],因为有可能存的值是一个数组
_start = _finish = _endofstorage = nullptr;
}
二 vector的容量操作
2.1 size函数
?一般的容器,我们都有size和capacity两个函数 来获取其容器大小,在vector中我们也有这两个函数,这里我们通过 指针-指针的差值来 计算其实际值。
?代码如下:
?
size_t size() const {
return _finish - _start;
}
2.2 capacity函数
?代码如下:
size_t capacity() const {
return _endofstorage - _start;
}size_t capacity() const {
return _endofstorage - _start;
}
2.3 reserve函数
? 在库中,reserve 修改容量时,size 是不会发生变化的(因为有效元素个数不变),若空间容量扩大则 capacity 会相应的进行扩大,若空间容量缩小时 capacity 是不会发生变化的。
? reserve的思想就是把原来的空间舍弃掉,重新开一段大空间。
代码如下:
?
//扩容
void reserve( size_t n) {
if (n > capacity()) {
//开始扩容
T* tmp = new T[n];
size_t sz = size();//提前算出size(),用来把原值赋值给新空间
if (_start) {
for (size_t i = 0; i < sz; i++) {
tmp[i] = _start[i];
}
delete[] _start;//避免内存泄漏
}
//指针指向新空间
_start = tmp;
_finish = _start + sz;
_endofstorage = _start + n;
}
}
2.4 resize函数
?resize 修改有效元素个数时,size 会进行相应的扩大或缩小变化,capacity 不一定会变化(有效元素增多时,若容量足够则capacity不变,否则会扩容;有效元素减少时,capacity 不变)
?resize的两个操作如下:
- 1.如果n小于当前的size,则数据个数缩小到n
- 2.如果n大于于当前的size,则说明空间不够需要增容,并且将size扩大到n
? 注意,这里val得用T的默认构造。?
?代码示例:
//resize
void resize(size_t n, const T& val = T()) {
if (n <= size()) {
_finish = _start + n;
}
else {
reserve(n);
while (_finish < _start + n) {
*_finish = val;
++_finish;
}
}
}
三迭代器?
? vector的迭代器就是原生指针,因此直接返回指针即可:
?
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;
}
四 元素修改函数
4.1 insert函数
?在指定pos位置进行插入元素
?但是这里却有一个很坑的点,那就是不小心写出来的代码就会引起迭代器失效的问题。
? 因为插入后,我们可能会发生扩容,pos指针会失效,这里我们先记录一下pos位置和起始位置的差值,扩容后让pos指针指向新空间。
void insert(iterator pos, const T& val) {
assert(pos >= _start);
assert(pos <= _finish);
if (_finish == _endofstorage) {
size_t len = pos - _start;
reserve(capacity() == 0 ? 4 : capacity() * 2);
pos = _start + len;
}
iterator end = _finish - 1;
while (end >= pos) {
*(end + 1) = *end;
--end;
}
*pos = val;
++_finish;
}
但要注意,这样的话,外部的pos指针怎么办呢?
这里是值传递,形参的改变是不会改变实参的,所以说外面的pos依旧没有实现更新操作,依旧会失效。
正确写法是通过返回值去解决问题的,返回的是迭代器,即新插入元素的位置。
正确代码为:
?
iterator insert(iterator pos, const T& val) {
assert(pos >= _start);
assert(pos <= _finish);
if (_finish == _endofstorage) {
size_t len = pos - _start;
reserve(capacity() == 0 ? 4 : capacity() * 2);
pos = _start + len;
}
iterator end = _finish - 1;
while (end >= pos) {
*(end + 1) = *end;
--end;
}
*pos = val;
++_finish;
return pos;
}
4.2 erase()
? 这里主要的就是从后往前删除的,这点需要大家注意一下。
? 同时,erase也会发生迭代器失效问题,因此要返回值避免迭代器失效。
代码如下:
?
iterator erase(iterator pos) {
assert(pos >= _start);
assert(pos < _finish);
iterator it = pos + 1;
while (it < _finish) {
*(it - 1) = *it;
++it;
}
--_finish;
return pos;
}
4.3 push_back()
插入尾部元素,直接复用insert.
void push_back(const T& val) {
insert(end(), val);
}
4.4 pop_back()?
删除尾部元素,直接把_finish--就好。
void pop_back()
{
assert(_start); //注意判空
--_finish;
}
五 元素访问
?5.1 []的重载
? 直接放回数组中的数据即可
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(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);
}
}
//区间构造
template <class InputIterator>
vector(InputIterator first, InputIterator last) {
while (first != last) {
push_back(*first);
++first;
}
}
void swap(vector<T>& v) {
std::swap(v._start, _start);
std::swap(v._finish, _finish);
std::swap(v._endofstorage, _endofstorage);
}
//拷贝构造
vector(const vector<T>& v) {
reserve(v.capacity());
for (auto& x : v) {
push_back(x);
}
}
//移动构造
vector(vector<T>&& v) {
swap(v);
}
//赋值重载
vector<T>& operator=(const vector<T>& v) {
vector<T> tmp(v);
swap(tmp);
return *this;
}
//移动赋值
vector<T>& operator=(vector<T>&& v) {
swap(v);
return *this;
}
七 完整代码和测试代码
?
#pragma once
#include<iostream>
#include<cassert>
using namespace std;
namespace My {
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() {
}
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);
}
}
//区间构造
template <class InputIterator>
vector(InputIterator first, InputIterator last) {
while (first != last) {
push_back(*first);
++first;
}
}
void swap(vector<T>& v) {
std::swap(v._start, _start);
std::swap(v._finish, _finish);
std::swap(v._endofstorage, _endofstorage);
}
//拷贝构造
vector(const vector<T>& v) {
reserve(v.capacity());
for (auto& x : v) {
push_back(x);
}
}
//移动构造
vector(vector<T>&& v) {
swap(v);
}
//赋值重载
vector<T>& operator=(const vector<T>& v) {
vector<T> tmp(v);
swap(tmp);
return *this;
}
//移动赋值
vector<T>& operator=(vector<T>&& v) {
swap(v);
return *this;
}
//扩容
void reserve( size_t n) {
if (n > capacity()) {
//开始扩容
T* tmp = new T[n];
size_t sz = size();//提前算出size(),用来把原值赋值给新空间
if (_start) {
for (size_t i = 0; i < sz; i++) {
tmp[i] = _start[i];
}
delete[] _start;//避免内存泄漏
}
//指针指向新空间
_start = tmp;
_finish = _start + sz;
_endofstorage = _start + n;
}
}
//resize
void resize(size_t n, const T& val = T()) {
if (n <= size()) {
_finish = _start + n;
}
else {
reserve(n);
while (_finish < _start + n) {
*_finish = val;
++_finish;
}
}
}
iterator insert(iterator pos, const T& val) {
assert(pos >= _start);
assert(pos <= _finish);
if (_finish == _endofstorage) {
size_t len = pos - _start;
reserve(capacity() == 0 ? 4 : capacity() * 2);
pos = _start + len;
}
iterator end = _finish - 1;
while (end >= pos) {
*(end + 1) = *end;
--end;
}
*pos = val;
++_finish;
return pos;
}
void push_back(const T& val) {
insert(end(), val);
}
iterator erase(iterator pos) {
assert(pos >= _start);
assert(pos < _finish);
iterator it = pos + 1;
while (it < _finish) {
*(it - 1) = *it;
++it;
}
--_finish;
return pos;
}
void pop_back()
{
assert(_start); //注意判空
--_finish;
}
T& operator[](size_t pos) {
assert(pos < size());
return _start[pos];
}
const T& operator[](size_t pos) const {
assert(pos < size());
return _start[pos];
}
size_t capacity() const {
return _endofstorage - _start;
}
size_t size() const {
return _finish - _start;
}
//析构
~vector() {
delete[] _start; //注意一定要加[]
_start = _finish = _endofstorage = nullptr;
}
private:
iterator _start = nullptr;
iterator _finish = nullptr;
iterator _endofstorage = nullptr;
};
void test_vector1()
{
vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
v.push_back(4);
v.push_back(5);
for (size_t i = 0; i < v.size(); i++)
{
cout << v[i] << " ";
}
cout << endl;
vector<int>::iterator it = v.begin();
while (it != v.end())
{
*it *= 10;
cout << *it << " ";
++it;
}
cout << endl;
for (auto e : v)
{
cout << e << " ";
}
cout << endl;
}
void test_vector2()
{
int i = 0;
int j(1);
int k = int(2);
vector<int*> v1;
v1.resize(10);
vector<string> v2;
//v2.resize(10, string("xxx"));
v2.resize(10, "xxx");
for (auto e : v1)
{
cout << e << " ";
}
cout << endl;
for (auto e : v2)
{
cout << e << " ";
}
cout << endl;
}
void test_vector3()
{
vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
v.push_back(4);
v.push_back(5);
v.push_back(6);
v.push_back(7);
for (auto e : v)
{
cout << e << " ";
}
cout << endl;
vector<int>::iterator it = v.begin() + 2;
v.insert(it, 30);
for (auto e : v)
{
cout << e << " ";
}
cout << endl;
//v.insert(v.begin(), 30);
v.insert(v.begin() + 3, 30);
for (auto e : v)
{
cout << e << " ";
}
cout << endl;
}
void test_vector4()
{
vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
v.push_back(4);
v.push_back(5);
v.push_back(6);
v.push_back(7);
for (auto e : v)
{
cout << e << " ";
}
cout << endl;
auto pos = v.begin();
v.erase(pos);
for (auto e : v)
{
cout << e << " ";
}
cout << endl;
v.erase(v.begin() + 3);
for (auto e : v)
{
cout << e << " ";
}
cout << endl;
}
//void test_vector5()
//{
// // 1 2 3 4 5
// // 1 2 3 4 5 6
// // 2 2 3 4 5
// std::vector<int> v;
// v.push_back(1);
// v.push_back(2);
// v.push_back(3);
// v.push_back(4);
// v.push_back(5);
// //v.push_back(6);
// for (auto e : v)
// {
// cout << e << " ";
// }
// cout << endl;
// auto it = v.begin();
// while (it != v.end())
// {
// // vs2019进行强制检查,erase以后认为it失效了,不能访问,访问就报错
// if (*it % 2 == 0)
// {
// v.erase(it);
// }
// ++it;
// }
// for (auto e : v)
// {
// cout << e << " ";
// }
// cout << endl;
//}
void test_vector5()
{
//std::vector<int> v;
vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
v.push_back(4);
v.push_back(4);
v.push_back(5);
v.push_back(6);
for (auto e : v)
{
cout << e << " ";
}
cout << endl;
auto it = v.begin();
while (it != v.end())
{
if (*it % 2 == 0)
{
it = v.erase(it);
}
else
{
++it;
}
}
for (auto e : v)
{
cout << e << " ";
}
cout << endl;
}
void test_vector6()
{
vector<string> v;
v.push_back("111111111111111111111");
v.push_back("111111111111111111111");
v.push_back("111111111111111111111");
v.push_back("111111111111111111111");
v.push_back("111111111111111111111");
for (auto e : v)
{
cout << e << " ";
}
cout << endl;
}
void test_vector7()
{
vector<int> v1;
v1.push_back(1);
v1.push_back(1);
v1.push_back(1);
v1.push_back(1);
v1.push_back(1);
vector<int> v2(v1);
for (auto e : v1)
{
cout << e << " ";
}
cout << endl;
for (auto e : v2)
{
cout << e << " ";
}
cout << endl;
vector<int> v3;
v3.push_back(10);
v3.push_back(20);
v3.push_back(30);
v3.push_back(40);
v1 = v3;
for (auto e : v1)
{
cout << e << " ";
}
cout << endl;
}
void test_vector8()
{
//vector<int> v0(10, 0);
vector<string> v1(10, "xxxx");
for (auto e : v1)
{
cout << e << " ";
}
cout << endl;
vector<int> v2;
v2.push_back(10);
v2.push_back(20);
v2.push_back(30);
v2.push_back(40);
vector<int> v3(v2.begin(), v2.end());
string str("hello world");
vector<int> v4(str.begin(), str.end());
for (auto e : v3)
{
cout << e << " ";
}
cout << endl;
for (auto e : v4)
{
cout << e << " ";
}
cout << endl;
}
}
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!