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

对于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>size
    v.resize(8);
    for (auto a : v)
    {
      cout << a << " ";
    }
    cout << endl;
    //n>capacity
    v.resize(15, "yyyy");
    for (auto e : v)
    {
      cout << e << " ";
    }
    cout << endl;
    //n<size
    v.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;
  }
}

运行:

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