C++之模拟实现vector(上)

简介: C++之模拟实现vector(上)

前言

因为学习了vector的相关知识,了解了vector大部分接口的底层实现原理,所以我决定自己模拟实现一个mini版的vector类,用来加深对vector各方面知识的理解。

如果有错误或不足之处,还望各位读者小伙伴们指出。


一、包含的相关头文件

#include<iostream>
#include<assert.h>
#include<vector>//要使用vector类,要记得包含这个头文件
using namespace std;

二、构造和析构

1.构造函数

1.无参

vector()
      :_start(nullptr)
      , _finish(nullptr)
      , _endOfStorage(nullptr)
    {}

2.n个T型元素进行初始化

1.普通

vector(size_t n, const T& value = T())
      :_start(nullptr)
      , _finish(nullptr)
      , _endOfStorage(nullptr)
    {
      reserve(n);
      //for (size_t i = 0; i < n; ++i)
      //{
      //  push_back(value);
      //}
      while (n--)
      {
        push_back(value);
      }
    }

2.特殊

因为,编译器会匹配最优匹配的函数进行调用。

为了避免将用n个Int型元素构造一个vector型的对象的函数调用匹配到下面的用T类型的迭代器初始化vector型的对象的构造函数(会发生错误的间接寻址),我们就得重载一个用n个Int数据初始化vector的构造函数

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);
      }
    }

3.T型迭代器

template<class InputIterator>
    vector(InputIterator first, InputIterator last)
      :_start(nullptr)
      , _finish(nullptr)
      , _endOfStorage(nullptr)
    {
      while (first != last)
      {
        push_back(*first);
        first++;
      }
    }

2.拷贝构造

现代写法的优点在模拟实现string中已经介绍过,此处不再赘述。

//拷贝构造(现代写法)
    vector(const vector<T>& v)
      :_start(nullptr)
      , _finish(nullptr)
      , _endOfStorage(nullptr)
    {
      vector<T> temp(v.begin(), v.end());
      Swap(temp);
    }

自己实现的Swap可以避免深拷贝,提高效率

void Swap(vector<T>& v)
    {
      std::swap(_start, v._start);
      std::swap(_finish, v._finish);
      std::swap(_endOfStorage, v._endOfStorage);
    }

3.赋值运算符重载

//赋值运算符重载
    vector<T>& operator= (vector<T> v)
    {
      Swap(v);
      return *this;
    }

4.析构函数

//析构
    ~vector()
    {
      delete[] _start;
      _start = _finish = _endOfStorage = nullptr;
    }

三、iterator

Vector的迭代器是一个原生指针

typedef T* iterator;
    typedef const T* const_iterator;

1.普通对象

返回迭代器

iterator begin()
    {
      return _start;
    }
    iterator end()
    {
      return _finish;
    }

2.const对象

返回const迭代器

const_iterator begin() const
    {
      return _start;
    }
    const_iterator end() const
    {
      return _finish;
    }

四、modify

1.push_back

尾插

void push_back(const T& x)
    {
      if (_finish == _endOfStorage)//插入前要判断空间是否满了
      {
        size_t newcapacity = (capacity() == 0) ? 4 : 2 * capacity();//要坚持是否第一次扩容
        reserve(newcapacity);
      }
      *_finish = x;
      _finish++;
    }

2.pop_back

尾删

void pop_back()
    {
      assert(!empty());//如果空间中没有元素就不能再尾删了
      _finish--;
    }

3.insert(含迭代器失效问题)

某个位置插入元素

这里有一个迭代器失效的问题,要小心处理

iterator insert(iterator pos, const T& x)
    {
      assert(pos >= _start);
      //assert(pos < _finish);
      assert(pos <= _finish);
      if (_finish == _endOfStorage)//如果插入操作进行了扩容,则原pos指针会失效(异地扩容会改变地址)
      {
        size_t len = pos - _start;
        size_t newcapacity = (capacity() == 0) ? 4 : 2 * capacity();
        reserve(newcapacity);
        //更新pos
        pos = _start + len;
      }
      iterator end = _finish;//挪动元素
      while (end > pos)
      {
        *end = *(end - 1);
        end--;
      }
      *pos = x;//插入元素
      _finish++;
      return pos;//pos是传值传参,因此函数内pos的更新不会使函数外的pos被更新(即,函数外的pos仍然失效)因此为了继续在函数外使用pos,我们把更新后的pos作为返回值传回去,更新函数外的pos
    }

具体如何处理下文的测试函数部分有介绍。

4.erase(含迭代器失效问题)

某位置删除一个元素

此处的迭代器意义发生改变,即迭代器失效

iterator erase(iterator pos)
    {
      assert(pos >= _start);
      assert(pos < _finish);
      //iterator begin = pos + 1;
      //while (begin < _finish)
      //{
      //  *(begin - 1) = *begin;
      //  begin++;
      //}
      iterator begin = pos;
      while (begin < _finish - 1)
      {
        *begin = *(begin + 1);
        begin++;
      }
      --_finish;
      return pos;
    }

具体如何处理下文的测试函数部分有介绍。

5.clear

void clear()
    {
      _finish = _start;
    }


相关文章
|
4月前
|
存储 编译器 C++
【C++】vector介绍+模拟实现
【C++】vector介绍+模拟实现
|
28天前
|
存储 编译器 C语言
【c++丨STL】vector的使用
本文介绍了C++ STL中的`vector`容器,包括其基本概念、主要接口及其使用方法。`vector`是一种动态数组,能够根据需要自动调整大小,提供了丰富的操作接口,如增删查改等。文章详细解释了`vector`的构造函数、赋值运算符、容量接口、迭代器接口、元素访问接口以及一些常用的增删操作函数。最后,还展示了如何使用`vector`创建字符串数组,体现了`vector`在实际编程中的灵活性和实用性。
53 4
|
9天前
|
存储 对象存储 C++
C++ 中 std::array<int, array_size> 与 std::vector<int> 的深入对比
本文深入对比了 C++ 标准库中的 `std::array` 和 `std::vector`,从内存管理、性能、功能特性、使用场景等方面详细分析了两者的差异。`std::array` 适合固定大小的数据和高性能需求,而 `std::vector` 则提供了动态调整大小的灵活性,适用于数据量不确定或需要频繁操作的场景。选择合适的容器可以提高代码的效率和可靠性。
31 0
|
13天前
|
存储 编译器 C语言
【c++丨STL】vector模拟实现
本文深入探讨了 `vector` 的底层实现原理,并尝试模拟实现其结构及常用接口。首先介绍了 `vector` 的底层是动态顺序表,使用三个迭代器(指针)来维护数组,分别为 `start`、`finish` 和 `end_of_storage`。接着详细讲解了如何实现 `vector` 的各种构造函数、析构函数、容量接口、迭代器接口、插入和删除操作等。最后提供了完整的模拟实现代码,帮助读者更好地理解和掌握 `vector` 的实现细节。
26 0
|
2月前
|
存储 C++ 索引
【C++打怪之路Lv9】-- vector
【C++打怪之路Lv9】-- vector
26 1
|
2月前
|
安全 测试技术 C++
【C++篇】从零实现 C++ Vector:深度剖析 STL 的核心机制与优化2
【C++篇】从零实现 C++ Vector:深度剖析 STL 的核心机制与优化
77 6
|
2月前
|
安全 测试技术 C++
【C++篇】从零实现 C++ Vector:深度剖析 STL 的核心机制与优化1
【C++篇】从零实现 C++ Vector:深度剖析 STL 的核心机制与优化
93 7
|
2月前
|
编译器 C++
【C++】—— vector模拟实现
【C++】—— vector模拟实现
|
2月前
|
编译器 C语言 C++
【C++篇】解密 STL 动态之魂:全面掌握 C++ vector 的高效与优雅
【C++篇】解密 STL 动态之魂:全面掌握 C++ vector 的高效与优雅
62 3
|
2月前
|
C++
【C++】C++ STL探索:Vector使用与背后底层逻辑(三)
【C++】C++ STL探索:Vector使用与背后底层逻辑