【C++初阶】vector 核心接口和模拟实现

🎬 博主名称键盘敲碎了雾霭
🔥 个人专栏 : 《C语言》《数据结构》 《C++》 《Matlab》 《Python》

⛺️指尖敲代码,雾霭皆可破


文章目录

  • 一、vector常用接口
    • [1.1 构造函数](#1.1 构造函数)
    • [1.2 reserve](#1.2 reserve)
    • [1.3 resize](#1.3 resize)
    • [1.4 insert](#1.4 insert)
    • [1.5 erase](#1.5 erase)
  • 二、string与vector
    • [2.1 区别](#2.1 区别)
    • [2.2 注意点](#2.2 注意点)
  • 三、Vector模拟实现
    • [3.1 核心成员变量](#3.1 核心成员变量)
    • [3.2 迭代器](#3.2 迭代器)
    • [3.3 核心接口实现](#3.3 核心接口实现)
      • [3.3.1 reserve](#3.3.1 reserve)
      • 3.3.2push_back
      • [3.3.3 insert](#3.3.3 insert)
      • [3.3.4 erase](#3.3.4 erase)
      • [3.3.5 resize](#3.3.5 resize)
    • [3.4 构造与析构](#3.4 构造与析构)
      • [3.4.1 默认构造](#3.4.1 默认构造)
      • [3.4.2 迭代器区间构造(模板泛型)](#3.4.2 迭代器区间构造(模板泛型))
      • [3.4.3 拷贝构造](#3.4.3 拷贝构造)
      • [3.4.4 赋值运算符](#3.4.4 赋值运算符)
      • [3.4.5 析构函数](#3.4.5 析构函数)
    • [3.5 辅助接口](#3.5 辅助接口)
    • [3.6 泛型打印函数](#3.6 泛型打印函数)
  • 四、代码实现

一、vector常用接口

以下为成员函数

1.1 构造函数

cpp 复制代码
	vector<int> v1;
	vector<int> v2(10,1);
	vector<int> v3(++v2.begin(), --v2.end());
	vector<int> v4(v2);
  • 遍历的三种方式
cpp 复制代码
	for (int i = 0; i < v3.size(); i++)
	{
		cout << v3[i] << " ";
	}
	cout << endl;
	vector<int>::iterator vit = v3.begin();
	while (vit != v3.end())
	{
		cout << *vit << " ";
		vit++;
	}
	cout << endl;
	for (auto tmp : v3)
	{
		cout << tmp << " ";
	}
	cout << endl;

1.2 reserve


reserve不会缩容(与string里的reserve不同,与平台无关)

cpp 复制代码
	vector<int> v;
	v.reserve(100);
	size_t size = v.capacity();
	for (int i = 0; i < 100; i++)
	{
		v.push_back(i);
		if (size!=v.capacity())
		{
			size = v.capacity();
			cout << size << endl;
		}
	}

vs按1.5倍扩容,会取整

1.3 resize


修改size,空间不够就扩容,不会缩容

cpp 复制代码
int main()
{
	vector<int> v1(10, 1);
	v1.reserve(20);
	cout << v1.size() << endl;
	cout << v1.capacity() << endl;

	v1.resize(15, 2);
	cout << v1.size() << endl;
	cout << v1.capacity() << endl;

	v1.resize(25, 4);
	cout << v1.size() << endl;
	cout << v1.capacity() << endl;

	v1.resize(5);
	cout << v1.size() << endl;
	cout << v1.capacity() << endl;
}

1.4 insert


不支持下标(用迭代器间接支持的)了,只支持迭代器

cpp 复制代码
	vector<int> v(10, 1);
	v.push_back(2);
	v.insert(v.begin(), 6);
	v.insert(v.begin()+3, 6);
	for (auto e : v)
	{
		cout << e << " ";
	}

1.5 erase


同样也不支持下标

二、string与vector

2.1 区别

  • vector没有流提取与流插入(<<、>>)
  • 两者不能相互替代
  • string可以返回c_str()并且有'\0'可以返回字符串,而vector没有
  • string支持用ASCII码表比较大小
  • string支持常量初始化,多了substr()、to_string()等其他函数
    ............等

2.2 注意点

vector还可以存储自定义类型

  • string
cpp 复制代码
	vector<string> v;
	string s1("hahaha");
	v.push_back(s1);
	v.push_back("xxx");
	for (auto e : v)
	{
		cout << e << endl;
	}
	return 0;
  • 二维数组
cpp 复制代码
	vector<int> a(5,1);
	vector<vector<int>> b(10, a);

三、Vector模拟实现

vector 底层本质是一个动态数组,能够自动管理内存,在元素超过容量时自动扩容。


3.1 核心成员变量

只需三个指针即可完整管理整个数组:

cpp 复制代码
template<class T>
class vector {
private:
    iterator _start = nullptr;          // 指向数据起始位置
    iterator _finish = nullptr;         // 指向最后一个有效数据的下一个位置
    iterator _end_of_storage = nullptr; // 指向容量末尾的下一个位置
};

通过指针运算得到常用属性:

  • size() = _finish - _start
  • capacity() = _end_of_storage - _start

3.2 迭代器

cpp 复制代码
iterator begin() { return _start; }
iterator end()   { return _finish; }

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

3.3 核心接口实现

3.3.1 reserve

cpp 复制代码
void reserve(size_t n) {
    if (n > capacity()) {
        iterator tmp = new T[n];
        size_t old_size = size();
        
        // 逐个拷贝 ------ 保证深拷贝
        for (size_t i = 0; i < old_size; i++)
            tmp[i] = _start[i];
        
        delete[] _start;
        _start = tmp;
        _finish = tmp + old_size;
        _end_of_storage = tmp + n;
    }
}

⚠️ 关键点 :使用循环赋值而非 memcpy,确保自定义类型的深拷贝正确性。

3.3.2push_back

cpp 复制代码
void push_back(const T& x) {
    if (_finish == _end_of_storage) {
        // 扩容策略:空容器分配4,否则翻倍
        reserve(empty() ? 4 : 2 * capacity());
    }
    *_finish++ = x;
}

3.3.3 insert

cpp 复制代码
iterator insert(iterator pos, const T& x) {
    assert(pos >= _start && pos <= _finish);
    
    size_t offset = pos - _start;  // 保存偏移量
    
    if (_finish == _end_of_storage) {
        reserve(empty() ? 4 : 2 * capacity());
    }
    
    pos = _start + offset;  // 重新定位
    
    // 从后往前移动元素
    for (iterator it = _finish - 1; it >= pos; --it)
        *(it + 1) = *it;
    
    *pos = x;
    ++_finish;
    return pos;  // 返回新位置,解决迭代器失效
}

3.3.4 erase

cpp 复制代码
iterator erase(iterator pos) {
    assert(pos >= _start && pos < _finish);
    
    for (iterator it = pos + 1; it != _finish; ++it)
        *(it - 1) = *it;
    
    --_finish;
    return pos;  // 返回删除位置的下一个元素
}

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

3.4 构造与析构

3.4.1 默认构造

cpp 复制代码
vector() = default;  // 指针已在声明时初始化为 nullptr

3.4.2 迭代器区间构造(模板泛型)

cpp 复制代码
template<class InputIterator>
vector(InputIterator first, InputIterator last) {
    while (first != last)
        push_back(*first++);
}

3.4.3 拷贝构造

cpp 复制代码
vector(const vector<T>& other) {
    reserve(other.size());
    for (const auto& x : other)
        push_back(x);
}

3.4.4 赋值运算符

cpp 复制代码
vector<T>& operator=(const vector<T>& other) {
    if (this != &other) {
        clear();
        reserve(other.size());
        for (const auto& x : other)
            push_back(x);
    }
    return *this;
}

3.4.5 析构函数

cpp 复制代码
~vector() {
    delete[] _start;
    _start = _finish = _end_of_storage = nullptr;
}

3.5 辅助接口

cpp 复制代码
T& operator[](size_t n) {
    assert(n < size());
    return _start[n];
}

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

size_t size()     const { return _finish - _start; }
size_t capacity() const { return _end_of_storage - _start; }
bool empty()      const { return _finish == _start; }

void clear() { _finish = _start; }
void pop_back() { assert(!empty()); --_finish; }

3.6 泛型打印函数

cpp 复制代码
template<typename Container>
void print(const Container& c, const char* sep = " ") {
    for (const auto& x : c)
        cout << x << sep;
    cout << endl;
}

四、代码实现

cpp 复制代码
#pragma once
#include<iostream>
#include<assert.h>
#include<string>
using namespace std;
namespace A
{
	template<class T>
	class vector
	{
	public:
		typedef T* iterator;
		typedef const T* const_iterator;
		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())
			{
				iterator tmp = new T[n];
				size_t old_size = size();
				//memcpy(tmp, _start, sizeof(T) * size());
				for (size_t i = 0; i < size(); i++)
				{
					tmp[i] = _start[i];
				}
				delete[] _start;
				_start = tmp;
				_finish = tmp + old_size;
				_end_of_storage = tmp + n;
			}
		}

		void clear()
		{
			_finish = _start;
		}
		vector<T>& operator=(const vector<T>& v)
		{
			if (&v != this)
			{
				clear();
				reserve(v.size());
				for (auto& e : v)
				{
					push_back(e);
				}
			}
			return *this;
		}
		//void swap(vector<T>& v)
		//{
		//	std::swap(_start, v._start);
		//	std::swap(_finish, v._finish);
		//	std::swap(_end_of_storage, v._end_of_storage);
		//}
		//vector<T> operator=(vector<T> v)
		//{
		//	swap(v);
		//	return *this;
		//}
		vector() = default;
		vector(const vector<T>& v)
		{
			reserve(v.size());
			for (size_t i = 0; i < v.size(); i++)
			{
				push_back(v[i]);
			}
		}
		~vector()
		{
			if (_start)
			{
				delete[] _start;
			}
			_finish = _end_of_storage = _start = nullptr;
		}
		size_t size()const
		{
			return _finish - _start;
		}
		size_t capacity()const
		{
			return _end_of_storage - _start;
		}
		T& operator[](size_t n)const
		{
			assert(n < size());
			return _start[n];
		}
		void push_back(const T& x)
		{
			if (_end_of_storage == _finish)
			{
				reserve(capacity()==0 ? 4 : capacity() * 2);
			}
			*_finish = x;
			_finish++;
		}
		void pop_back()
		{
			_finish--;
		}
		iterator insert(iterator pos, const T& x)
		{
			if (_end_of_storage == _finish)
			{
				size_t len = pos - _start;
				reserve(capacity() == 0 ? 4 : capacity() * 2);
				pos = _start + len;
			}
			auto end = _finish - 1;
			while (end >= pos)
			{
				*(end + 1) = *end;
				end--;
			}
			*pos = x;
			_finish++;
			return pos;
		}
		iterator erase(iterator pos)
		{
			auto it = pos + 1;
			while (it!=_finish)
			{
				*(it - 1) = *it;
				it++;
			}
			_finish--;
			return pos;
		}
		void resize(size_t n,const T& val=T())
		{
			if (n < size())
			{
				_finish = _start + n;
			}
			else
			{
				reserve(n);
				size_t len = _start+n-_finish;
				while (len--)
				{
					push_back(val);
				}
			}
			
		}
		template<class Contain_iterator>
		vector(Contain_iterator start, Contain_iterator finish)
		{
			while (start!=finish)
			{
				push_back(*start);
				start++;
			}
		}
		template<class Contain>
		void print_contain(Contain& v)
		{
			for (size_t i = 0; i < v.size(); i++)
			{
				cout << v[i] << " ";
			}
			cout << endl;
			for (auto ch : v)
			{
				cout << ch << " ";
			}
			cout << endl;
			auto it = v.begin();
			while (it != v.end())
			{
				cout << *it << " ";
				it++;
			}
			cout << endl;
		}
		vector(size_t n, const T& val = T())
		{
			reserve(n);
			for (size_t i = 0; i < n; i++)
			{
				push_back(val);
			}

		}
		vector(int n, const T& val = T())
		{
			reserve(n);
			for (size_t i = 0; i < n; i++)
			{
				push_back(val);
			}

		}
	private:
		iterator _start=nullptr;
		iterator _finish=nullptr;
		iterator _end_of_storage=nullptr;
	};
	void test();
	void test01();
	void test03();
}
复制代码
# 文章结语
感谢你读到这里~我是「**键盘敲碎了雾霭**」,愿这篇文字帮你敲开了技术里的小迷雾 💻

如果内容对你有一点点帮助,不妨给个暖心三连吧👇
👍 **点赞** | ❤️ **收藏** | ⭐ **关注**
(听说三连的小伙伴,代码一次编译过,bug绕着走~)

你的支持,就是我继续敲碎技术雾霭的最大动力 🚀

🐶 小彩蛋:

  /^ ^\
 / 0 0 \
 V\ Y /V
  / - \
/    |

V__) ||

复制代码
摸一摸毛茸茸的小狗,赶走所有疲惫和bug~我们下篇见 ✨
相关推荐
Lyyaoo.2 小时前
【设计模式】工厂模式
java·开发语言·设计模式
今晚打老虎2 小时前
限时回归了
c++
老四啊laosi2 小时前
[C++进阶] 22. unordered_set && unordered_map使用
c++·unordered_map·unordered_set
宵时待雨2 小时前
C++笔记归纳20:智能指针
开发语言·c++·笔记
jinanwuhuaguo2 小时前
OpenClaw 2026.4.5 深度解读
android·开发语言·人工智能·kotlin·openclaw
小小马喽_Thendras2 小时前
ScheduledExecutorService 和Timer的区别
java·开发语言
报错小能手2 小时前
ios开发方向——swift内存基础
开发语言·ios·swift
minji...2 小时前
Linux 多线程(四)线程等待,线程分离,线程管理,C++多线程,pthread库
linux·运维·开发语言·网络·c++·算法
麦德泽特3 小时前
基于 Go 语言的 Modbus 项目实战:构建高性能、可扩展的工业通信服务器
服务器·开发语言·golang·modbus·rtu