C++初阶--自我实现vector

2024-01-20 23:36
文章标签 c++ 初阶 vector 自我实现

本文主要是介绍C++初阶--自我实现vector,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

实现模板

#include<assert.h>
#include<string.h>
#include<iostream>
#include<list>
using namespace std;
namespace fnc
{template<class T>class vector{public:typedef T* iterator;typedef const T* const_iterator;//构造函数vector(){}//复制拷贝vector(const vector<T>& v){reserve(v.capacity());for (const auto& a : v){push_back(a);}			}//迭代器区间构造template<class InputIterator>vector(InputIterator first, InputIterator last){while (first != last){push_back(*first);first++;}}vector(size_t n, const T& val = T()){resize(n, val);}vector(int n, const T& val = T()){resize(n, val);}void swap(vector<T>& v){std::swap(_start, v._start);std::swap(_finish, v._finish);std::swap(_endofstorage, v._endofstorage);}//赋值vector<T>& operator=(vector<T> v){swap(v);return *this;}//析构函数~vector(){if (_start){delete[] _start;_start = _finish = _endofstorage = nullptr;}}//返回对应的位置iterator begin(){return _start;}iterator end(){return _finish;}const_iterator begin() const{return _start;}const_iterator end() const{return _finish;}void reserve(size_t n){if (n > capacity()){size_t old = size();T* tmp = new T[n];if (_start){//memcpy(tmp, _start, sizeof(T) * old);//不建议for (int i = 0; i < old; i++){tmp[i] = _start[i];}delete[] _start;}_start = tmp;_finish = _start + old;_endofstorage = _start + n;}}void resize(size_t n, T val = T()){if (n > size()){if (n > capacity()){reserve(n);}//先记住之前的位置while (_finish < _start + n){*_finish = val;_finish++;}}else{_finish = _start + n;}}void push_back(const T& x){//满扩容if (_finish == _endofstorage){size_t newcapacity =capacity() == 0 ? 1 : capacity() * 2;reserve(newcapacity);}*_finish = x;_finish++;}void pop_back(){assert(size() > 0);--_finish;}iterator insert(iterator pos,const T& x){//确保pos是正确的范围内assert(pos >= _start && pos < _finish);if (_finish == _endofstorage){size_t distance = pos - _start;size_t newcapacity = capacity() == 0 ? 1 : capacity() * 2;reserve(newcapacity);pos = _start + distance;}//插入腾出空间//memmove(pos + 1, pos, sizeof(T) * (_finish - pos));//不建议iterator end = _finish - 1;while (end >= pos){*(end + 1) = *end;end--;}*pos = x;_finish++;return pos;}iterator erase(iterator pos){assert(pos >= _start && pos < _finish);//将对应位置挤掉//memmove(pos, pos + 1, sizeof(T) * (_finish - pos - 1));//不建议iterator it = pos + 1;while (it < _finish){*(it - 1) = *it;it++;}--_finish;return pos;}size_t capacity(){return _endofstorage - _start;}size_t size(){return _finish - _start;}size_t capacity() const{return _endofstorage - _start;}size_t size() const{return _finish - _start;}T& operator[](size_t pos){assert(pos < size());return _start[pos];}private:iterator _start=nullptr;iterator _finish=nullptr;iterator _endofstorage=nullptr;};

首先我们看vector的成员函数,都是通过迭代器来确定具体位置的,

_start表示vector的起始位置,
_finish表示vector有效存储的结束位置,
_endodstorage表示当前开辟的空间指向最后的地址位置

下面通过实例来讲解一些需要注意的地方。

vector和const_vector

![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/6514a69d140f48a5a192bd266659ca71.png
对于vector来说,实际上就是C语言的数组,这也就表明vector存储的元素的地址空间是连续的,所以这里的迭代器实际上表示的就是原始指针,但为了区别是否有const修饰,需要对他们进行简单的封装。
在这里插入图片描述

被const修饰的迭代器,只具有可读性,对于一些只读的函数,要多加const重载函数。

例子:

void print_vector(const vector<int>& v){for (auto a : v){cout << a << " ";}cout << endl;}void test_vector1(){vector<int> v;v.push_back(1);v.push_back(2);v.push_back(3);v.push_back(4);vector<int>::iterator it = v.begin();while (it != v.end()){cout << *it << " ";it++;}cout << endl;for (auto a : v){cout << a << " ";}cout << endl;for (int i = 0; i < v.size(); i++){cout << v[i] << " ";}cout << endl;v.insert(v.begin(), 111);print_vector(v);v.insert(v.begin(), 110);print_vector(v);v.erase(v.begin() + 4);print_vector(v);v.erase(v.begin());print_vector(v);}

如果这里没有添加const修饰的begin和end函数,那么将会报错,因为涉及到权限放大的问题。

在这里插入图片描述

resize()和reserve()

reserve()也就是对vector的容量进行扩容,
在这里插入图片描述
这里需要对原先的存储进行,方便后面进行对成员变量迭代器的定位。
在这里插入图片描述
这里要注意,_finish和_endofstorge都是相对于_start来取相对位置的,因为创建了一个新的空间。

resize()就是改变vector()的有效容量
在这里插入图片描述
T是泛型类型,T()表示取对应的默认构造参数,内置类型会取到0,或者nullptr;
自定义类型会根据构造参数进行初始化,取到对应的值;

void test_vector2(){vector<int> myvector;// set some initial content:for (int i = 1; i < 10; i++) myvector.push_back(i);myvector.resize(5);myvector.resize(8, 100);myvector.resize(12);cout << "myvector contains:";for (int i = 0; i < myvector.size(); i++)cout << ' ' << myvector[i];std::cout << endl;}

在这里插入图片描述

拷贝构造和赋值

这里会发现,我是在成员变量进行了声明,构造函数没有进行初始化;
一开始,我只是在构造函数进行了初始化,而在拷贝构造中没有进行初始化,那么由于这两个函数是构成重载的,所以像一些有指针的,由于没有进行初始化,会变成野指针,这样就会报错。
所以在这里总结:
在这里插入图片描述

void test_vector3(){vector<int> v;v.push_back(1);v.push_back(2);v.push_back(3);v.push_back(4);vector<int> v1 = v;cout << "原来的v1 ";for (auto a : v1){cout << a << " ";}cout << endl;vector<int> v2;v2.push_back(22);v2.push_back(33);v2.push_back(44);v2.push_back(55);v1=v2;cout << "赋值后的v1 ";for (auto a : v1){cout << a << " ";}cout << endl;}

在这里插入图片描述

深浅拷贝的问题

先看例子

void test_vector4(){vector<string> v;v.reserve(10);v.push_back("xxx");v.push_back("xxx");v.push_back("xxx");v.push_back("xxx");v.push_back("xxx");v.push_back("xxx");for (auto a : v){cout << a << " ";}cout << endl;//n>sizev.resize(8);for (auto a : v){cout << a << " ";}cout << endl;//n>capacityv.resize(15, "yyyy");for (auto e : v){cout << e << " ";}cout << endl;//n<sizev.resize(3);for (auto e : v){cout << e << " ";}cout << endl;}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

迭代器失效问题

void test_vector5(){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);//要求删除所有偶数vector<int>::iterator 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;}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

vector的其他构造

void test_vector6(){vector<int> v1;v1.push_back(1);v1.push_back(2);v1.push_back(3);v1.push_back(4);vector<int> v2(v1.begin(), v1.end());for (auto e : v2){cout << e << " ";}cout << endl;list<int> lt;lt.push_back(11);lt.push_back(22);lt.push_back(33);lt.push_back(44);vector<int> v3(lt.begin(), lt.end());for (auto e : v3){cout << e << " ";}cout << endl;int a[] = { 100,200,300 };vector<int> v4(a, a + 3);for (auto e : v4){cout << e << " ";}}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

void test_vector7(){vector<string> v1(5, "1234");for (auto e : v1){cout << e << " ";}cout << endl;vector<int> v2(5, 1);for (auto e : v2){cout << e << " ";}cout << endl;}
}

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

这篇关于C++初阶--自我实现vector的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/627707

相关文章

C++中detach的作用、使用场景及注意事项

《C++中detach的作用、使用场景及注意事项》关于C++中的detach,它主要涉及多线程编程中的线程管理,理解detach的作用、使用场景以及注意事项,对于写出高效、安全的多线程程序至关重要,下... 目录一、什么是join()?它的作用是什么?类比一下:二、join()的作用总结三、join()怎么

C++中全局变量和局部变量的区别

《C++中全局变量和局部变量的区别》本文主要介绍了C++中全局变量和局部变量的区别,全局变量和局部变量在作用域和生命周期上有显著的区别,下面就来介绍一下,感兴趣的可以了解一下... 目录一、全局变量定义生命周期存储位置代码示例输出二、局部变量定义生命周期存储位置代码示例输出三、全局变量和局部变量的区别作用域

C++中assign函数的使用

《C++中assign函数的使用》在C++标准模板库中,std::list等容器都提供了assign成员函数,它比操作符更灵活,支持多种初始化方式,下面就来介绍一下assign的用法,具有一定的参考价... 目录​1.assign的基本功能​​语法​2. 具体用法示例​​​(1) 填充n个相同值​​(2)

c++ 类成员变量默认初始值的实现

《c++类成员变量默认初始值的实现》本文主要介绍了c++类成员变量默认初始值,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧... 目录C++类成员变量初始化c++类的变量的初始化在C++中,如果使用类成员变量时未给定其初始值,那么它将被

C++中NULL与nullptr的区别小结

《C++中NULL与nullptr的区别小结》本文介绍了C++编程中NULL与nullptr的区别,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编... 目录C++98空值——NULLC++11空值——nullptr区别对比示例 C++98空值——NUL

C++ Log4cpp跨平台日志库的使用小结

《C++Log4cpp跨平台日志库的使用小结》Log4cpp是c++类库,本文详细介绍了C++日志库log4cpp的使用方法,及设置日志输出格式和优先级,具有一定的参考价值,感兴趣的可以了解一下... 目录一、介绍1. log4cpp的日志方式2.设置日志输出的格式3. 设置日志的输出优先级二、Window

从入门到精通C++11 <chrono> 库特性

《从入门到精通C++11<chrono>库特性》chrono库是C++11中一个非常强大和实用的库,它为时间处理提供了丰富的功能和类型安全的接口,通过本文的介绍,我们了解了chrono库的基本概念... 目录一、引言1.1 为什么需要<chrono>库1.2<chrono>库的基本概念二、时间段(Durat

C++20管道运算符的实现示例

《C++20管道运算符的实现示例》本文简要介绍C++20管道运算符的使用与实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧... 目录标准库的管道运算符使用自己实现类似的管道运算符我们不打算介绍太多,因为它实际属于c++20最为重要的

Visual Studio 2022 编译C++20代码的图文步骤

《VisualStudio2022编译C++20代码的图文步骤》在VisualStudio中启用C++20import功能,需设置语言标准为ISOC++20,开启扫描源查找模块依赖及实验性标... 默认创建Visual Studio桌面控制台项目代码包含C++20的import方法。右键项目的属性:

c++中的set容器介绍及操作大全

《c++中的set容器介绍及操作大全》:本文主要介绍c++中的set容器介绍及操作大全,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录​​一、核心特性​​️ ​​二、基本操作​​​​1. 初始化与赋值​​​​2. 增删查操作​​​​3. 遍历方