前言
STL 容器是 C++ 开发中绕不开的'神兵利器',而 vector 作为最常用的动态数组容器,更是新手入门的核心内容。但多数时候,我们只是'会用'它,却对底层逻辑一知半解——比如它如何动态扩容?push_back 的内存管理是怎样的?构造函数的匹配规则为何如此复杂?
与其停留在'黑盒调用'的层面,不如亲手模拟实现一个 vector:从底层的指针管理(_start/_finish/_endofstorage),到核心接口(push_back/resize/operator[]),再到构造、拷贝等特殊函数的实现,一步步揭开 STL 容器的面纱。
本文以'实用、易懂'为核心,带你用 C++ 手动实现一个具备基础功能的 vector,既能加深对容器原理的理解,也能锻炼 C++ 的底层编程能力。
一、vector 的介绍
简单说,vector 是 C++ 里可以动态变大小的数组。它既保留了普通数组'连续存储、下标访问高效'的优点,又解决了普通数组'大小固定、不能自动扩容'的痛点。
它的底层逻辑是动态分配的数组。当你往 vector 里加新元素时,它会自动管理内存。如果当前数组存满了,就会重新分配一块更大的空间,把旧元素全搬过去,再继续存新元素。不过这个'搬家'操作开销不低,所以 vector 会提前多分配一些额外空间,避免频繁搬家。
它的特点可以总结成'优劣势分明':
- 优势:访问元素(用下标)、在末尾增删元素,效率都很高;
- 劣势:在中间/开头增删元素,效率很低(因为要挪动大量元素);
- 对比其他容器:
vector的访问更快,但灵活增删不如list。
二、vector 的默认成员函数
1、构造函数
namespace ayj // 避免与标准库 std::vector 命名冲突 {
template <class T>
class vector {
public:
typedef T* iterator;
typedef const T* const_iterator;
private:
iterator _start = nullptr; // 指向第一个有效元素
iterator _finish = nullptr; // 指向最后一个有效元素的下一个位置
iterator _endofstorage = nullptr; // 指向已分配空间的末尾
};
}
这里有一个特殊的编译陷阱需要注意。按道理来说,我们用 vector<int> v(10, 1) 是想用 10 个 1 构造一个 vector,这没啥问题吧?但有时候会编译不通过,报错还跟迭代器范围构造相关。
这是因为 vector<int> v(10, 1) 会误匹配范围构造函数版本(10/1 被当作 InputIterator),此时 会把 10 当作指针解引用,触发未定义行为(崩溃)。


