C++ vector 核心功能解析与实现

发布于:2025-04-22 ⋅ 阅读:(13) ⋅ 点赞:(0)

目录

整体结构概述

赋值运算符重载

下标运算符重载

内存管理函数

元素访问函数

插入和删除操作

完整代码


在C++标准库中, vector  是一个非常常用的动态数组容器,它能够自动管理内存,并且提供了丰富的操作接口。本文将通过分析一段手写  vector  的核心代码,深入理解  vector  的底层实现原理。

整体结构概述

我们实现的  vector  类模板主要包含以下几个关键部分:

1. 数据成员:用于管理动态数组的内存和元素范围。

2. 赋值运算符重载:实现对象之间的赋值操作。

3. 下标运算符重载:支持通过  []  访问元素。

4. 内存管理函数: reserve  和  resize  用于控制动态数组的容量和大小。

5. 元素访问函数: front  和  back  用于获取容器的首元素和尾元素。

6. 插入和删除操作: push_back 、 pop_back 、 insert  和  erase  用于元素的增删。

cpp

template <typename T>

class vector {

private:

    iterator _start; // 指向动态数组起始位置

    iterator _finish; // 指向最后一个有效元素的下一个位置

    iterator _end_of_storage; // 指向动态数组容量的末尾位置

public:
    typesdef T* iterator;
    typesdef const T* const_iterator;

    // 以下是具体成员函数的实现

};

赋值运算符重载

cpp

vector<T>& operator=(vector<T>& v) {

    swap(v);

    return *this;

}

现代化写法

该函数实现了  vector  对象之间的赋值操作。通过调用  swap  函数交换当前对象和传入对象的内部数据( _start 、 _finish  和  _end_of_storage ),从而高效地完成赋值。 swap  函数的具体实现通常会交换两个对象的资源,而不是逐个复制元素,这样可以提高效率。

下标运算符重载

cpp

T& operator[](size_t pos) {

    assert(pos < size());

    return _start[pos];

}



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

    assert(pos < size());

    return _start[pos];

}

这两个函数实现了通过  []  操作符访问  vector  中的元素。第一个函数是非  const  版本,用于修改元素;第二个函数是  const  版本,用于在  const vector  对象上读取元素。通过  assert  确保访问的下标在有效范围内,防止越界访问。

内存管理函数

 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)*sz);
					for (size_t i = 0;i < sz;i++)
					{
						tmp[i] = _start[i];
					}
					delete[]_start;
				}
				_start = tmp;
				_finish = _start + sz;
				_end_of_storage = _start + n;

			}
		}

 reserve  函数用于确保  vector  的容量至少为  n 。如果  n  大于当前容量,会分配一块新的更大的内存,将原有的元素逐个复制到新内存中,然后释放旧内存,并更新  _start 、 _finish  和  _end_of_storage  指针。

resize  函数

cpp

void resize(size_t n, const T& val = T()) {

    if (n < size()) {

        _finish = _start + n;

    } else {

        reserve(n);

        while (_finish != _start + n) {

            *_finish = val;

            ++_finish;

        }

    }

}

 resize  函数用于改变  vector  的大小。如果  n  小于当前大小,会截断  vector ;如果  n  大于当前大小,会先调用  reserve  确保有足够的容量,然后将新增位置初始化为  val 。

元素访问函数

 front  函数


 

cpp

T& front() {

    return *_start;

}



const T& front() const {

    return *_start;

}



 front  函数用于获取  vector  的首元素。非  const  版本允许修改首元素, const  版本则用于在  const vector  对象上获取首元素。

 back  函数

cpp

T& back() {

    return *(_finish - 1);

}



const T& back() const {

    return *(_finish - 1);

}

 back  函数用于获取  vector  的尾元素。同样分为非  const  和  const  版本,分别用于修改和读取尾元素。

插入和删除操作

 push_back  函数



cpp

void push_back(const T& x) {

    insert(end(), x);

}

 push_back  函数在  vector  的末尾插入一个元素,它通过调用  insert  函数实现。

 pop_back  函数

cpp

void pop_back() {

    erase(end() - 1);

}

 pop_back  函数删除  vector  的尾元素,通过调用  erase  函数实现。

 erase  函数


 

cpp

iterator erase(iterator pos) {

    iterator begin = pos + 1;

    while (begin != _finish) {

        *(begin - 1) = *begin;

        ++begin;

    }

    _finish--;

    return pos;

}



 erase  函数删除指定位置的元素。通过将该位置之后的元素逐个向前移动,覆盖要删除的元素,然后更新  _finish  指针。

 insert  函数

cpp

iterator insert(iterator pos, const T& x) {

    assert(pos <= _finish);

    if (_finish == _end_of_storage) {

        size_t len = pos - _start;

        size_t new_cap = (capacity() == 0) ? 4 : capacity() * 2;

        reserve(new_cap);

        pos = _start + len;

    }

    iterator end = _finish - 1;

    while (end >= pos) {

        *(end + 1) = *end;

        end--;

    }

    *pos = x;

    _finish++;

    return pos;

}

 insert  函数在指定位置插入一个元素。如果当前容量已满,会先调用  reserve  扩大容量,然后将插入位置之后的元素逐个向后移动,腾出空间插入新元素,并更新  _finish  指针。

通过以上代码的实现,我们可以对  vector  的核心功能有一个更深入的理解,掌握动态数组的内存管理和元素操作的底层原理。在实际开发中,合理使用  vector  可以提高代码的效率和可读性。

完整代码

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
#include<assert.h>
namespace ldg
{
	template<class T>
	class vecctor
	{
	public:
		//原生指针
		typedef T* iterator;
		typedef const T* const_iterator;

		size_t size() {
			return _finish - _start;
		}

		size_t capacity()
		{
			return _end_of_storage - _start;
		}

		bool empty()const 
		{
			return _start == _finish;
		}

		iterator begin()
		{
			return _start;
		}

		iterator cend()
		{
			return _finish;
		}
		const_iterator cbegin()const
		{
			return _start;
		}

		const_iterator cend()const
		{
			return _finish;
		}
		//构造和销毁
		vector()
			:_start(nullptr)
			, _finish(nullptr)
			, _end_of_storage(nullptr)
		{}

		vector(size_t n,const T& val=T())
			:_start(nullptr)
			, _finish(nullptr)
			, _end_of_storage(nullptr)
		{
			reserve(n);
			while (n--) push_back(val);
			
		}

		vector(int  n, const T& val = T())
			:_start(new T[n])
			, _finish(_start+n)
			, _end_of_storage(_finish)
		{
			for (int i = 0;i < n;i++)_start[i] = val;
		}

		template <class Inititerator>
		vector(Inititerator first, Inititerator last)
		{
			while (first != last)
			{
				push_back(*first);
				first++;
			}
		}

		//vector(const vector<T>& v)
		//	:_start(nullptr)
		//	, _finish(nullptr)
		//	, _end_of_storage(nullptr)
		//{
		//	_start = new T[v.capacity()];
		//	//memccpy(_start,v._start,sizeof(T)*v.size());
		//	for (size_t i = 0;i < size();i++)
		//	{
		//		_start[i] = v._start[i];
		//	}
		//	_finish = _start + v.size();
		//	_ens_of_storage = _start + v.capacity();
		//}

		vector(const vector<T>& v)
			:_start(nullptr)
			, _finish(nullptr)
			, _end_of_storage(nullptr)
		{
			reserve(v.capacity());
			for (auto e : v)push_back(e);
			
		}

		~vector()
		{
			if (_start) {
				delete[]_start;
				_start = _finish = _end_of_storage = nullptr;
			}
		}

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

		vector<T>& operator=(vector<T>& v)
		{
			swap(v);
			return *this;
		}

		T& operator[](size_t pos)
		{
			assert(pos < size());
			return _start[pos];
		}

		const T& operator[](size_t pos)const
		{
			assert(pos < size());
			return _start[pos];
		}

		
		void reserve(size_t n)
		{
			if (n > capacity())
			{
				size_t sz = size();
				t* tmp = new t[n];
				if (_start)
				{
					//memcpy(_tmp,_start,sizeof(T)*sz);
					for (size_t i = 0;i < sz;i++)
					{
						tmp[i] = _start[i];
					}
					delete[]_start;
				}
				_start = tmp;
				_finish = _start + sz;
				_end_of_storage = _start + n;

			}
		}
		void resize(size_t n, const T& val = T())
		{
			if (n < size())
			{
				_finish = _start + n;
			}
			else
			{
				reserve(n);

				while (_finish != _start + n)
				{
					*finish = val;
					++_finish;
				}
			}
		}

		T& front()
		{
			return *_start;
		}

		const T& front()const
		{
			return *_start;
		}

		T& back()
		{
			return *(finish-1);
		}

		const T& back()const
		{
			return *(finish - 1);
		}

		void push_back(const T& x)
		{
			insert(end(), x);
		}

		void pop_back()
		{
			ease(end() - 1);
		}
		//pos位置插入x
		
		//删除pos位置,返回pos+1
		iterator erase(iterator pos)
		{
			iterator begin = pos + 1;
			while (begin = _finish)
			{
				*(begin - 1) = *begin;
				++begin;
			}
			_finish--;
			return pos;
		}

		iterator insert(iterator pos, const T& x)
		{
			assert(pos <= finish);
			if (_finish == _end_of_storage)
			{
				size_t len = pos-start;
				size_t newst = (capacity() == 0) ? 4 : capacity() * 2;
				reserve(newst);
				pos = _start + len;//防止迭代器失效
			}
			iterator end = _finish - 1;
			while (end >= pos)
			{
				*(end + 1) = *end;
				end--;
			}
			*pos = x;
			finish--;
			return pos;//防止迭代器失效
		}
		private:
			iterator _start;
			iterator _finish;
			iterator _end_of_storage;
	};


网站公告

今日签到

点亮在社区的每一天
去签到