【C++之容器篇】造轮子:模拟实现vector类

news/2025/2/9 1:58:17/

目录

    • 前言
    • 一、项目结构
      • 1. vector的简介
      • 2. 项目结构
    • 二、vector的底层结构
    • 三、默认成员函数
      • 1. 构造函数
        • (1)无参构造函数
      • 2. 拷贝构造函数
      • 3. 析构函数
      • 4. 赋值运算符重载函数
    • 四、迭代器
      • 1. 普通对象的正向迭代器
      • 2. const 对象的正向迭代器
    • 五、容量接口
      • 1. size()
      • 2. capacity()
      • 3. reserve()
      • 4. resize()
    • 六、元素访问接口
      • 1. operator[](size_t pos)
        • (1)const T& operator[](size_t pos)
        • (2)const T& operator[](size_t pos) const
      • 2. at(size_t pos)
        • (1)T& at(size_t pos)
      • 3. front()
      • 4. back()
    • 七、修改接口
      • 1. push_back(const T& x)
      • 2. pop_back()
      • 3.iterator insert(iterator pos,T val = T()))

前言

vector本质就是一个支持顺序存储数据,并且容量支持修改得到顺序表。但是vector的底层结构实现相比于之前实现的string来说略有不同。string中的底层结构是通过一个指针数组和两个变量来标识数组中数据的变化。vector是通过三个迭代器来标识上述过程。

一、项目结构

1. vector的简介

在这里插入图片描述

2. 项目结构

这个项目有两个文件,一个是test.cpp文件,另一个是vector.h文件。test.cpp文件主要是用来测试实现的vector的代码逻辑。vector.h文件主要是模拟实现vector的代码逻辑。
在这里插入图片描述
在这里插入图片描述

二、vector的底层结构

  1. 效果图:
    在这里插入图片描述
    在这里插入图片描述

  2. 代码实现

namespace hjt
{// 实现vectortemplate <class T>class vector{public:typedef T* iterator;typedef const T* const_iterator;private:iterator _start;// 指向存储的第一个有效数据iterator _finish;// 指向存储的最后一个有效数据的下一个位置iterator _endofstorage;// 指向能够存储的最后一个位置的下一个位置};
}

代码中是通过三个迭代器来实现底层的。

  • _start:指向存储的第一个有效数据
  • _finish:指向存储的最后一个有效数据的下一个位置
  • _endofstorage: 指向能够存储的最后一个位置的下一个位置
    其实这个实现方法和string中的实现方法其实差不多,相当于_start表示空间的起始地址,_finish表示有效数据的个数,_endofstorage表示vector的实际容量。

三、默认成员函数

1. 构造函数

在这里插入图片描述

(1)无参构造函数

  • 代码
	// 无参构造函数vector():_start(nullptr),_finish(nullptr),_endofstorage(nullptr){}
  • 练习:
int main()
{hjt::vector<int> v1;hjt::vector<char> v2;hjt::vector<double> v3;hjt::vector<string> v4;return 0;
}

分析:v1表示一个存储int类型的vector对象,v2表示一个存储char类型的vector对象,v3表示一个存储double类型的vector对象,v4表示一个存储string类型对象的vector对象。

2. 拷贝构造函数

3. 析构函数

4. 赋值运算符重载函数

四、迭代器

1. 普通对象的正向迭代器

在这里插入图片描述

  • 代码:
// 普通迭代器iterator begin(){return _start;}iterator end(){return _finish;}
  • 代码:使用

2. const 对象的正向迭代器

  • 代码:
// const迭代器const_iterator begin() const{return _start;}const_iterator end() const{return _finish;}

五、容量接口

1. size()

  • 代码:
		size_t size() const{return _finish - _start;}

2. capacity()

  • 代码:
 		size_t capacity() const{return _endofstorage - _start;}

3. reserve()

  • 代码:
// 扩容void reserve(size_t n){if (n > capacity()){size_t sz = size();T* tmp = new T[n];if (_start){memcpy(tmp, _start, sizeof(T) * size());delete[]_start;}_start = tmp;_finish = _start + sz;_endofstorage = _start + n;}}

4. resize()

  • 测试代码:
int main()
{hjt::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;cout << "size:" << v.size() << endl;cout << "capacity:" << v.capacity() << endl;v.resize(100,6);for (auto& e : v){cout << e << " ";}cout << endl;cout << "size:" << v.size() << endl;cout << "capacity:" << v.capacity() << endl;return 0;
}

运行结果:
在这里插入图片描述

  • 测试代码2:
int main()
{hjt::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;cout << "size:" << v.size() << endl;cout << "capacity:" << v.capacity() << endl;v.resize(3, 6);for (auto& e : v){cout << e << " ";}cout << endl;cout << "size:" << v.size() << endl;cout << "capacity:" << v.capacity() << endl;return 0;
}

运行结果:
在这里插入图片描述

  • 测试代码3:
int main()
{hjt::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;cout << "size:" << v.size() << endl;cout << "capacity:" << v.capacity() << endl;for (auto& e : v){cout << e << " ";}cout << endl;v.reserve(60);cout << "size:" << v.size() << endl;cout << "capacity:" << v.capacity() << endl;for (auto& e : v){cout << e << " ";}cout << endl;v.resize(50, 6);for (auto& e : v){cout << e << " ";}cout << endl;cout << "size:" << v.size() << endl;cout << "capacity:" << v.capacity() << endl;return 0;
}

运行结果:
在这里插入图片描述

六、元素访问接口

1. operator[](size_t pos)

(1)const T& operator[](size_t pos)

  • 代码:
	T& operator[](size_t pos){return _start[pos];}
  • 测试代码:
int main()
{hjt::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 (size_t i = 0; i < v.size(); i++){cout << v[i] << " ";}cout << endl;return 0;
}

运行结果:
在这里插入图片描述

(2)const T& operator[](size_t pos) const

  • 代码:
	const T& operator[](size_t pos) const{return _start[pos];}
  • 测试代码:

2. at(size_t pos)

(1)T& at(size_t pos)

  • 代码:
		T& at(size_t pos){return _start[pos];}
  • 测试代码:
int main()
{hjt::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 (size_t i = 0; i < v.size(); i++){cout << v.at(i) << " ";}cout << endl;return 0;
}

运行结果:
在这里插入图片描述

3. front()

  • 代码:
// frontT& front() const{return *_start;}

4. back()

  • 代码:
// back()T& back() const{return *(_finish - 1);}

测试:

int main()
{hjt::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);cout << "front:" << v.front() << endl;cout << "back:" << v.back() << endl;
}

运行结果:
在这里插入图片描述

七、修改接口

1. push_back(const T& x)

  • 代码:
// 尾插void push_back(const T& x){if (_finish == _endofstorage){// 需要进行扩容reserve(capacity() == 0 ? 4 : capacity() * 2);}*_finish = x;_finish++;}
  • 测试:
// 测试尾插
int main()
{hjt::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);hjt::vector<int>::iterator vit = v.begin();while (vit != v.end()){cout << *vit << " ";vit++;}cout << endl;cout << v.size() << endl;cout << v.capacity() << endl;for (auto e : v){cout << e << " ";}cout << endl;return 0;
}

运行结果:
在这里插入图片描述

2. pop_back()

  • 代码:
// 尾删void pop_back(){assert(_finish > _start);_finish--;}
  • 测试代码:
int main()
{hjt::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);hjt::vector<int>::iterator vit = v.begin();while (vit != v.end()){cout << *vit << " ";vit++;}cout << endl;v.pop_back();v.pop_back();v.pop_back();for (auto& e : v){cout << e << " ";}cout << endl;return 0;
}

运行结果:
在这里插入图片描述
没有数据继续删除:
在这里插入图片描述

3.iterator insert(iterator pos,T val = T()))

  • 代码:
// insert()iterator insert(iterator pos, T val = T()){assert(pos >= _start && pos <= _finish);if (_finish == _endofstorage){// 扩容// 如果需要进行扩容,注意更新迭代器,否则会导致迭代器失效size_t n = pos - _start;reserve(capacity() == 0 ? 4 : capacity() * 2);pos = _start + n;}// 挪动数据iterator end = _finish - 1;while (end >= pos){*(end + 1) = *end;end--;}// 插入数据*pos = val;_finish++;return pos;}
  • 测试代码1:头插+尾插
// 测试insert
int main()
{hjt::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;v.insert(v.begin(), 10);for (auto& e : v){cout << e << " ";}cout << endl;v.insert(v.end(), 10);for (auto& e : v){cout << e << " ";}cout << endl;
}
  • 测试代码2:在偶数前插入66
// 在偶数前面插入66
int main()
{hjt::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;hjt::vector<int>::iterator vit = v.begin();while (vit != v.end()){if (*vit % 2 == 0){vit = v.insert(vit, 66);vit++;}vit++;}for (auto& e : v){cout << e << " ";}cout << endl;return 0;
}

运行结果:
在这里插入图片描述


http://www.ppmy.cn/news/24210.html

相关文章

C++入门教程||C++ 数据类型||C++ 变量类型

C 数据类型 使用编程语言进行编程时&#xff0c;需要用到各种变量来存储各种信息。变量保留的是它所存储的值的内存位置。这意味着&#xff0c;当您创建一个变量时&#xff0c;就会在内存中保留一些空间。 您可能需要存储各种数据类型&#xff08;比如字符型、宽字符型、整型…

ccc-Logistic Regression-李宏毅(5)

文章目录Step 1: Function SetStep 2: Goodness of a FunctionStep 3: Find the best functionWhy not Logistic Regression Square ErrorDiscriminative v.s. GenerativeMulti-class Classification(3 Class)Limitation of Logistic RegressionCascading logistic regression…

【openGauss实战8】Schema的图文解读

&#x1f4e2;&#x1f4e2;&#x1f4e2;&#x1f4e3;&#x1f4e3;&#x1f4e3; 哈喽&#xff01;大家好&#xff0c;我是【IT邦德】&#xff0c;江湖人称jeames007&#xff0c;10余年DBA及大数据工作经验 一位上进心十足的【大数据领域博主】&#xff01;&#x1f61c;&am…

【RabbitMQ五】——RabbitMQ路由模式(Routing)

RabbitMQ路由模式前言RabbitMQ模式的基本概念为什么要使用Rabbitmq 路由模式RabbitMQ路由模式组成元素路由模式完整代码Pom文件引入RabbtiMQ依赖RabbitMQ工具类生产者消费者1消费者2运行结果截图前言 通过本篇博客能够简单使用RabbitMQ的路由模式。 本篇博客主要是博主通过官网…

【JavaScript】35_包装类与垃圾回收机制

10、包装类 在JS中&#xff0c;除了直接创建原始值外&#xff0c;也可以创建原始值的对象 通过 new String() 可以创建String类型的对象 通过 new Number() 可以创建Number类型的对象 通过 new Boolean() 可以创建Boolean类型的对象 但是千万不要这么做 包装类&#xff1…

box86 exagear

box86 box86编译的时候是静态编译&#xff0c;所以编译好后一个可执行没任何依赖直接拷贝走就能运行&#xff0c;注意&#xff0c;box86需要32位的arm库&#xff08;armhf&#xff09;,麒麟系统有打包好的armhf库的包&#xff0c;可以直接用&#xff0c;缺的再单补。box86做指令…

用 Python 调用 GPT-3 API

用 Python 调用 GPT-3 API GPT-3 是去年由 Open AI 推出的语言机器学习模型。它因其能够写作、写歌、写诗&#xff0c;甚至写代码而获得了广泛的媒体关注&#xff01;该工具免费使用&#xff0c;只需要注册一个电子邮件即可。 GPT-3 是一种叫 transformer 的机器学习模型。具体…

前端对于深拷贝和浅拷贝的应用和思考

浅拷贝 浅拷贝 &#xff1a; 浅拷贝是指对基本类型的值拷贝&#xff0c;以及对对象类型的地址拷贝。它是将数据中所有的数据引用下来&#xff0c;依旧指向同一个存放地址&#xff0c;拷贝之后的数据修改之后&#xff0c;也会影响到原数据的中的对象数据。最简单直接的浅拷贝就…