stl_vector容器
本文参考了这位大佬的github,直接先使用了它的基本头文件,在此基础上创建实现自己容器,反向理解底层代码
学习参考步骤:https://blog.csdn.net/weixin_43729695/article/details/102980558
-
Alloc.h 分配内存,使用二级配置器,必需,有需要的可以先看,alloc解析
-
TypeTraits.h 类型萃取,必需
-
Construct.h 容器的构造和析构,必需,简单不解析
-
Allocator.h alloc.h和construct.h的直接上级,封装函数,必需,简单不解析
-
Itearator.h 迭代器,必需,提供迭代器的各种参数
-
Functional.h 实现小于、等于等仿函数,这个可以以后拓展写
-
Utility.h 算法中使用,实现pair,其他容器建立后,回头很简单不解析
-
ReserveseIterator.h 反向迭代器
-
Algorithm.h 经典算法,必需
-
UninitializedFunctions.h 未定义的初始变量的初始化,必需,对底层内存变量的操作,也好理解
这十个文件也可以直接从这https://download.csdn.net/download/qq_38223012/20680865 下载
刚刚开始学习,就完成简单的构造、析构和一些常用的功能,实现一个简单的vector容器,也不用太复杂,简单实现就好
注意为了区别代码:自己写的命名空间改成了mySTL
工具:visual studio 2019
亲自手写过,并添加详细注释
主要完成int类型的功能,其他类型只完成基本创建, insert等自行添加
完整版:https://blog.csdn.net/qq_38223012/article/details/119463625
stl_vector.h
#pragma once
#ifndef _STL_VECTOR_H_
#define _STL_VECTOR_H_
#include "../Includes/TypeTraits.h"
#include "../Includes/Algorithm.h"
#include "../Includes/Iterator.h"
#include "../Includes/ReverseIterator.h"
#include "../Includes/UninitializedFunctions.h"
#include "../Includes/Allocator.h"
namespace mySTL {
template<class T, class alloc = allocator<T>>
class vector {
public:
// vector的嵌套型别定义
typedef T value_type; // 元素类型
typedef T* pointer; // 指针类型
typedef T* iterator; // vector是线性空间,所以iterator普通指针
typedef T& reference; // 重构相关的左引用,引用类型
typedef size_t size_type; // 用于指明数组长度,它必须是一个正数
typedef ptrdiff_t difference_type; // 应保证足以存放同一数组中两个指针之间的差距,它有可能是负数。
private:
iterator start; //目前使用空间的开头
iterator finish; //目前使用空间的结尾
iterator endOfStorage; //目前可用空间的尾部
typedef alloc dataAllocator;
public:
//构造函数 // 构造类型
vector(): start(0), finish(0), endOfStorage(0){} // vector<int> vec;
//explicit防止类构造函数的隐式自动转换. //
explicit vector(const size_type n); // vector<int> vec(10);
vector(const size_type n, const value_type& val); // vector<int> vec(10, 1);
//析构函数
~vector();
public:
// 迭代器相关函数
iterator begin() { return start; }
iterator end() { return finish; }
// 容量相关函数
size_type size() const { return finish - start; }
size_type capacity() const { return endOfStorage - start; }
bool empty() const { return start == finish; }
void resize(size_type n, value_type val = value_type());
// 访问元素相关
reference operator[](const size_type i) { return *(begin() + i); }
reference front() { return *(begin()); }
reference back() { return *(end() - 1); }
// 修改容器相关的操作
// 清空容器,销毁容器中的所有对象并使容器的size为0,但不回收容器已有的空间
void clear();
void push_back(const value_type& val);
void pop_back();
iterator erase(iterator position);
iterator insert(iterator position, const value_type& val);
void insert(iterator position, const size_type& n, const value_type& val);
template <class InputIterator>
void insert(iterator position, InputIterator first, InputIterator last);
// 容器的空间配置器相关
alloc get_allocator() { return dataAllocator; }
private:
void destroyAndDeallocate(); // 析构并释放空间
void allocateAndFill(const size_type n, const value_type& val); // 分配空间并填充数值val
template<class InputIterator>
void reallocateAndCopy(iterator position, InputIterator first, InputIterator last);
void reallocateAndFill(iterator position, const size_type& n, const value_type& val);
size_type getNewCapacity(size_type len)const;
template<class InputIterator> // 判断是否内存够用,重新分配内存为原来的2倍
void insert_aux(iterator position, InputIterator first, InputIterator last, std::false_type);
template<class Integer>
void insert_aux(iterator position, Integer n, const value_type& value, std::true_type);
};
}
#include "../Detail/stl_vector.impl.h" //存放实现函数的位置
#endif
stl_vector.impl.h
#pragma once
namespace mySTL {
//***********************构造,析构相关***********************
//构造函数
template<class T, class alloc>
vector<T, alloc>::vector(const size_type n)
{
allocateAndFill(n, value_type());
}
template<class T, class alloc>
vector<T, alloc>::vector(const size_type n, const value_type& val)
{
allocateAndFill(n, val);
}
//析构函数
template<class T, class alloc>
vector<T, alloc>::~vector()
{
destroyAndDeallocate();
}
//*************和容器的容量相关******************************
template<class T, class alloc>
void vector<T, alloc>::resize(size_type n, value_type val)
{
if (n < size())
{
dataAllocator::destroy(start + n, finish);
finish = start + n;
}
else if (n > size() && n <= capacity())
{
auto lengthOfInsert = n - size();
//局部初始化,底层通过memset初始化,返回填充结束的尾部地址
finish = mySTL::uninitialized_fill_n(finish, lengthOfInsert, val);
}
else if (n > capacity())
{
auto lengthOfInsert = n - size();
// 以上三步为走
// 第一步,获取扩容大小,并返回扩容后总的大小,进行新的内存分配
// 第二步,copy当前vector数据,填充到新地址中, end指向原理容量大小的位置,
// 第三步,将扩充部分进行数据填充,end指向扩容后的尾部
T* newStart = dataAllocator::allocate(getNewCapacity(lengthOfInsert));
// 数据拷贝,底层通过memcopy实现,返回当前大小的尾部地址
T* newFinish = mySTL::uninitialized_copy(begin(), end(), newStart);
newFinish = mySTL::uninitialized_fill_n(newFinish, lengthOfInsert, val);
destroyAndDeallocate();
// 更新容器参数
start = newStart;
finish = newFinish;
endOfStorage = start + n;
}
}
//***************修改容器的相关操作**************************
template<class T, class alloc>
void vector<T, alloc>::clear()
{
dataAllocator::destroy(start, finish);
finish = start;
}
template<class T, class alloc>
void vector<T, alloc>::push_back(const value_type& val)
{
insert(end(), val);
}
template<class T, class alloc>
void vector<T, alloc>::pop_back()
{
--finish;
dataAllocator::destroy(finish);
}
// 清除某位置上元素
template<class T, class alloc>
typename vector<T, alloc>::iterator vector<T, alloc>::erase(iterator position)
{
iterator first = position, last = position + 1;
//尾部残留对象数
difference_type lenOfTail = end() - last;
//删去的对象数目
difference_type lenOfRemoved = last - first;
finish = finish - lenOfRemoved;
// 向前移动 lenOfRemoved距离
for (; lenOfTail != 0; --lenOfTail)
{
auto temp = (last - lenOfRemoved);
*temp = *(last++);
}
return position;
}
/********************* insert 函数实现解析 ************/
template<class T, class alloc>
typename vector<T, alloc>::iterator vector<T, alloc>::insert(iterator position, const value_type& val)
{
const auto index = position - begin();
insert(position, 1, val);
return begin() + index;
}
template<class T, class Alloc>
template<class InputIterator>
void vector<T, Alloc>::insert(iterator position, InputIterator first, InputIterator last) {
insert_aux(position, first, last, typename std::is_integral<InputIterator>::type());
}
template<class T, class alloc>
void vector<T, alloc>::insert(iterator position, const size_type& n, const value_type& val)
{
insert_aux(position, n, val, typename std::is_integral<size_type>::type()); // 判断是否int类型,是就实现插入,不是终止,因为没有写string类型的
}
template<class T, class alloc>
template<class InputIterator>
typename void vector<T, alloc>::insert_aux(iterator position, InputIterator first, InputIterator last, std::false_type)
{
difference_type locationLeft = endOfStorage - finish; // the size of left storage
difference_type locationNeed = distance(first, last);//last - first;
if (locationLeft >= locationNeed) {
if (finish - position > locationNeed) {
mySTL::uninitialized_copy(finish - locationNeed, finish, finish);
std::copy_backward(position, finish - locationNeed, finish);
std::copy(first, last, position);
}
else {
iterator temp = mySTL::uninitialized_copy(first + (finish - position), last, finish);
mySTL::uninitialized_copy(position, finish, temp);
std::copy(first, first + (finish - position), position);
}
finish += locationNeed;
}
else {
reallocateAndCopy(position, first, last);
}
}
template<class T, class alloc>
template<class Integer>
typename void vector<T, alloc>::insert_aux(iterator position, Integer n, const value_type& value, std::true_type)
{
//其作用是如果它的条件返回错误,则终止程序执行。
assert(n != 0);
difference_type locationLeft = endOfStorage - finish; // 未使用空间大小
difference_type locationNeed = n;
if (locationLeft >= locationNeed) // 当前容器满足插入空间大小
{
auto tempPtr = end() - 1;
for (; tempPtr - position >= 0; --tempPtr)
{
// placement new,就是在指针p所指向的内存空间创建一个T1类型的对象,
// 但是对象的内容是从T2类型的对象转换过来的(调用了T1的构造函数,T1::T1(value))。
// 就是在已有空间的基础上重新调整分配的空间
construct(tempPtr + locationNeed, *tempPtr);
}
mySTL::uninitialized_fill_n(position, n, value);
finish += locationNeed;
}
else
{
reallocateAndFill(position, n, value);
}
}
/********************* insert 函数解析结束 ************/
// 容器的空间配置器相关
/********************* 扩展内存大小, 并返回新的大小 ************/
template<class T, class alloc>
typename vector<T, alloc>::size_type vector<T, alloc>::getNewCapacity(size_type len)const{
size_type oldCapacity = endOfStorage - start; // 旧容器的容量
auto res = mySTL::max(oldCapacity, len); // 容器容量扩展量,选择大的
// 新容器的容量
// 如果未定义,则选择resize所定的,
// 如果定义了,容量*2,或者更大容量 + len(此时len比旧容量大)
size_type newCapacity = (oldCapacity != 0 ? (oldCapacity + res) : len);
return newCapacity;
}
template<class T, class alloc>
void vector<T, alloc>::destroyAndDeallocate()
{
if (capacity() != 0)
{
// destory负责调用类型的析构函数,销毁相应内存上的内容(但销毁后内存地址仍保留)
// deallocate负责释放内存,在此之前应调用destory销毁,将内存地址返回给系统
dataAllocator::destroy(start, finish);
dataAllocator::deallocate(start, capacity());
}
}
template<class T, class alloc>
typename void vector<T, alloc>::allocateAndFill(const size_type n, const value_type& val)
{
start = dataAllocator::allocate(n);
mySTL::uninitialized_fill_n(start, n, val);
finish = endOfStorage = start + n;
}
template<class T, class alloc>
template<class InputIterator>
void vector<T, alloc>::reallocateAndCopy(iterator position, InputIterator first, InputIterator last)
{
difference_type newCapacity = getNewCapacity(last - first);
T* newStart = dataAllocator::allocate(newCapacity);
T* newEndOfStorage = newStart + newCapacity;
T* newFinish = mySTL::uninitialized_copy(begin(), position, newStart);
newFinish = mySTL::uninitialized_copy(first, last, newFinish);
newFinish = mySTL::uninitialized_copy(position, end(), newFinish);
destroyAndDeallocate();
start = newStart;
finish = newFinish;
endOfStorage = newEndOfStorage;
}
template<class T, class alloc>
void vector<T, alloc>::reallocateAndFill(iterator position, const size_type& n, const value_type& val)
{
difference_type newCapcity = getNewCapacity(n);
T* newStart = dataAllocator::allocate(newCapcity);
T* newEndOfStorage = newStart + newCapcity;
T* newFinish = mySTL::uninitialized_copy(begin(), position, newStart);
newFinish = mySTL::uninitialized_fill_n(newFinish, n, val);
newFinish = mySTL::uninitialized_copy(position, end(), newFinish);
destroyAndDeallocate();
start = newStart;
finish = newFinish;
endOfStorage = newEndOfStorage;
}
}
后续还有一些拷贝函数,算法之类的,可以自行添加
stl_vector_test.h
#pragma once
#include "../p2_STL_Source/stl_vector.h"
#include <vector>
#include <array>
#include <cassert>
#include<iostream>
#include <iterator>
#include <string>
using namespace std;
namespace mySTL {
namespace vectorTest {
template<class T>
using stdVec = std::vector<T>; //取别名
template<class T>
using myVec = mySTL::vector<T>;
void print(std::vector<int> &v);
void myprint(mySTL::vector<int>& v);
void test01();
void test02();
void test03();
void test04();
void test05(); // 未写测试代码
void test06(); // 未写测试代码
}
}
stl_vector_test.cpp
#include "stl_vector_test.h"
namespace mySTL {
namespace vectorTest {
void print(std::vector<int>& v)
{
for (int i = 0; i < v.size(); i++)
{
cout << v[i] << " ";
}
cout << endl;
}
void myprint(mySTL::vector<int>& v)
{
for (int i = 0; i < v.size(); i++)
{
cout << v[i] << " ";
}
cout << endl;
}
void test01()
{
stdVec<string> v1(10, "xfy");
myVec<string> v2(10, "xfy");
cout << v1[0] << endl;
cout << v1.size()<< endl;
cout << v1.capacity() << endl;
cout << v2[0] << endl;
cout << v2.size() << endl;
cout << v2.capacity() << endl;
}
void test02()
{
stdVec<int> v1;
myVec<int> v2;
cout << v1.size() << endl;
cout << v2.size() << endl;
for (int i = 0; i < 10; i++)
{
v1.push_back(i + 1);
v2.push_back(i + 1);
}
cout << v1.size() << endl;
cout << v2.size() << endl;
print(v1);
myprint(v2);
v1.pop_back();
v1.pop_back();
v2.pop_back();
v2.pop_back();
print(v1);
myprint(v2);
cout << v1.capacity() << endl;
cout << v2.capacity() << endl;
v1.resize(20);
v2.resize(20);
cout << v1.size() << endl;
cout << v2.size() << endl;
cout << v1.capacity() << endl;
cout << v2.capacity() << endl;
}
void test03()
{
stdVec<int> v1;
myVec<int> v2;
cout << v1.size() << endl;
cout << v2.size() << endl;
for (int i = 0; i < 5; i++)
{
v1.push_back(i + 1);
v2.push_back(i + 1);
}
print(v1);
myprint(v2);
cout << v1.front() <<" "<< v1.back() << endl;
cout << v2.front() << " " << v2.back() << endl;
cout << v1[2]<< endl;
cout << v2[2]<< endl;
v1.insert(v1.begin(), 11);
v2.insert(v2.begin(), 11);
v1.insert(v1.begin() + 2, 11);
v2.insert(v2.begin() + 2, 11);
v1.insert(v1.end(), 11);
v2.insert(v2.end(), 11);
print(v1);
myprint(v2);
v1.erase(v1.begin());
v2.erase(v2.begin());
v1.erase(v1.end() - 1);
v2.erase(v2.end() - 1);
print(v1);
myprint(v2);
}
class testTemp
{
public:
//testTemp();
void setT(string name, int num)
{
this->name = name;
this->num = num;
}
void print_to()
{
cout << "nams: " << this->name << " num: " << this->num << endl;
}
private:
string name;
int num;
};
void test04()
{
testTemp tt;
tt.setT("san", 16);
stdVec<testTemp> v1;
myVec<testTemp> v2;
v1.push_back(tt);
v2.push_back(tt);
v1.front().print_to();
v2.front().print_to();
}
void test05()
{
}
void test06()
{
}
}
}