vector的底层实现!(万字长文详解!)
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了vector的底层实现!(万字长文详解!)相关的知识,希望对你有一定的参考价值。
vector的底层简单实现!
vector的成员变量
template<class T>
class vector
typedef T* iterator;//迭代器
typedef const T* const_iterator;
private:
iterator _start;
iterator _finish;
iterator _endofstorage;
;
reserve
void reserve(size_t n)
if (n > capacity())
T* temp = new T[n];
size_t OldSzie = size();
if (_start != nullptr)//万一一开始是空,那么就没有必要拷贝数据了!
for (size_t i = 0; i < OldSzie; i++)
temp[i] = _start[i];
delete[] _start;
_start = temp;
_finish = _start + OldSzie;
_endofstorage = _start + n;
push_back
void push_back(const T& value)
if (_finish == _endofstorage)
size_t newcapaciy = capacity() == 0 ? 4 : capacity() * 2;
reserve(newcapaciy);
*_finish = value;
_finish++;
构造函数
vector()
:_start(nullptr),
_finish(nullptr),
_endofstorage(nullptr)
template<class InputIterator>
vector(InputIterator first, InputIterator last)
: _start(nullptr),
_finish(nullptr),
_endofstorage(nullptr)
while (first != last)
push_back(*first);
first++;
构造函数的冲突
vector(size_t n, const T& val = T())
: _start(nullptr),
_finish(nullptr),
_endofstorage(nullptr)
reserve(n);
for (size_t i = 0; i < n; i++)
push_back(val);
而这个构造函数
vector(size_t n, const T& val = T());
解决办法
-
My_STL::vector<char> v((size_t)10, a);//进行强转!
-
//写一个函数重载只要有一个更匹配的函数就不会去调用上面的模板函数了! //因为调用模板函数还需要实例化 vector(int n, const T& val = T()) : _start(nullptr), _finish(nullptr), _endofstorage(nullptr) reserve(n); for (int i = 0; i < n; i++) push_back(val);
所以最后的完成版就是
vector()
:_start(nullptr),
_finish(nullptr),
_endofstorage(nullptr)
template<class InputIterator>
vector(InputIterator first, InputIterator last)
: _start(nullptr),
_finish(nullptr),
_endofstorage(nullptr)
while (first != last)
push_back(*first);
first++;
vector(size_t n, const T& val = T())
: _start(nullptr),
_finish(nullptr),
_endofstorage(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),
_endofstorage(nullptr)
reserve(n);
for (int i = 0; i < n; i++)
push_back(val);
析构函数
~vector()
delete[] _start;
_start = _finish _endofstorage = nullptr;
size
size_t size()const
return _finish - _start;
capacity
size_t capacity()const
return _endofstorage - _start;
begin
iterator begin()const
return _start;
end
iterator end()const
return _finish;
empty
bool empty()const
return _finish == _start;
pop_back
void pop_back()
assert(!empty());
--_finish;
[]重载
T& operator[](size_t pos)
assert(pos < size());
return _start[pos];
T& operator[](size_t pos)const
assert(pos < size());
return _start[pos];
resize
void resize(size_t n, T value = T())
if (n > capacity())
reserve(n);
if (n > size())
while (_finish < _start + n)
*_finish = value;
++_finish;
if (n < size())
_finish = _start + n;
insert——重点
但是即使是上面的写法也不能完全避免迭代器失效的问题!
因为我们只是避免了里面的迭代器失效!还有外面的迭代器失效我们无法避免!
int main()
My_STL::vector<int> v1;
v1.push_back(1);
v1.push_back(2);
v1.push_back(3);
v1.push_back(4);
My_STL::vector<int> ::iterator it = find(v1.begin(), v1.end(), 3);
v1.insert(it, 30);
cout << (*it) << endl;
return 0;
因为我们当里面发生扩容的时候!外面的迭代器还是指向的是旧的空间!这就是一个越界访问!是一个野指针!
==为了安全考虑所以当我们使用it之后无论它是否真的失效了!我们一律都认为它是失效的!==
==为了安全如果要再次使用it最好进行更新!==
iterator insert(iterator pos, const T& val)
assert(pos >= _start);
assert(pos <= _finish);
if (_finish == _endofstorage)
size_t len = pos - _start;
int NewCapacity = capacity() == 0 ? 4 : capacity() * 2;
reserve(NewCapacity);
pos = _start + len;
//这里一旦扩容!就会导致一个很严重的问题就是地址发生了改变!
iterator end = _finish - 1;
while (end >= pos)
*(end + 1) = *end;
--end;
*(pos) = val;
_finish++;
return pos;
我们可以使用==iterator==作为返回值!==返回插入后值的位置!==
这样我们可以在使用it之后 使用it接收这个返回值!更新it
int main()
My_STL::vector<int> v1;
v1.push_back(1);
v1.push_back(2);
v1.push_back(3);
v1.push_back(4);
My_STL::vector<int> ::iterator it = find(v1.begin(), v1.end(), 3);
it = v1.insert(it, 30);
cout << (*it) << endl;
return 0;
erase——重点
这样子写就可以在g++下面和vs下面的都是可以运行!就无关平台了!
clear
void clear()
_finish - _start;
swap
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());
swap(tmp);
赋值运算符重载
vector<T>& operator=(vector<T> v)
swap(v);
return *this;
使用memcpy实现reserve的缺陷——重要
总结
==这也是为什么我们在c++中使用new和delete的原因而不是使用malloc的free==
==因为new和delete会去自动的调用构造和析构函数而malloc和free却不会!和自定义类型其实不相符合!==
全部代码
#pragma once
#include <iostream>
#include<vector>
#include<assert.h>
using namespace std;
namespace My_STL
template<class T>
class vector
public:
typedef T* iterator;
typedef const T* const_iterator;
vector()
:_start(nullptr),
_finish(nullptr),
_endofstorage(nullptr)
template<class InputIterator>
vector(InputIterator first, InputIterator last)
: _start(nullptr),
_finish(nullptr),
_endofstorage(nullptr)
while (first != last)
push_back(*first);
first++;
vector(size_t n, const T& val = T())
: _start(nullptr),
_finish(nullptr),
_endofstorage(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),
_endofstorage(nullptr)
reserve(n);
for (size_t i = 0; i < n; i++)
push_back(val);
vector(const vector<T>& v)
: _start(nullptr),
_finish(nullptr),
_endofstorage(nullptr)
vector<T> tmp(v.begin(), v.end());
swap(tmp);
~vector()
delete[] _start;
_start = _finish = _endofstorage = nullptr;
vector<T>& operator=(vector<T> v)
swap(v);
return *this;
size_t size()const
return _finish - _start;
size_t capacity()const
return _endofstorage - _start;
iterator begin()const
return _start;
iterator end()const
return _finish;
T& operator[](size_t pos)
assert(pos < size());
return _start[pos];
T& operator[](size_t pos)const
assert(pos < size());
return _start[pos];
void reserve(size_t n)
if (n > capacity())
T* temp = new T[n];
size_t OldSzie = size();
if (_start != nullptr)
for (size_t i = 0; i < OldSzie; i++)
temp[i] = _start[i];
delete[] _start;
_start = temp;
_finish = _start + OldSzie;
_endofstorage = _start + n;
void resize(size_t n, T value = T())
if (n > capacity())
reserve(n);
if (n > size())
while (_finish < _start + n)
*_finish = value;
++_finish;
if (n < size())
_finish = _start + n;
void push_back(const T& value)
if (_finish == _endofstorage)
size_t newcapaciy = capacity() == 0 ? 4 : capacity() * 2;
reserve(newcapaciy);
*_finish = value;
_finish++;
bool empty()const
return _finish == _start;
void pop_back()
assert(!empty());
--_finish;
void clear()
_finish - _start;
void swap(vector<T>& v)
std::swap(_start, v._start);
std::swap(_finish, v._finish);
std::swap(_endofstorage, v._endofstorage);
iterator insert(iterator pos, const T& val)
assert(pos >= _start);
assert(pos < _finish);
if (_finish == _endofstorage)
size_t len = pos - _start;
int NewCapacity = capacity() == 0 ? 4 : capacity() * 2;
reserve(NewCapacity);
pos = _start + len;
iterator end = _finish - 1;
while (end >= pos)
*(end + 1) = *end;
--end;
*(pos) = val;
_finish++;
return pos;
iterator erase(iterator pos)
assert(pos >= _start);
assert(pos < _finish);
iterator begin = pos + 1;
while (begin < _finish)
*(begin-1) = *(begin);
++begin;
_finish--;
return pos;
private:
iterator _start;
iterator _finish;
iterator _endofstorage;
;
以上是关于vector的底层实现!(万字长文详解!)的主要内容,如果未能解决你的问题,请参考以下文章
万字长文详解Shardingsphere对XA分布式事务的支持