Step 01

骨架与内存模型

粘贴到作业纸 student/mini_vector/vector.hpp 底部不需要仓库,起步页已有全部工程文件

这一步不用改作业纸。三个字段和 empty / size / capacity 已经写好。编译后跑页面底部的空 vector 测试即可。工程文件在 起步页,编译问题见 常见问题。

Step 01 — 骨架与内存模型

std::vector 不是“一块已经构造好的数组”,而是:

data_      →  [ 已构造的 T ][ 已构造的 T ][ 未初始化内存 ][ 未初始化内存 ]
                |←      size_      →|←        capacity_ - size_        →|
  • size_:已经调用过构造函数的元素个数。push_back / emplace_back 让它 +1,pop_back / resize 缩小让它减少。
  • capacity_:allocate 向分配器要来的槽位数。reserve 只动它,不动 size_。
  • data_:指向这块内存的起点。capacity_ == 0 时它是 nullptr。

把这两件事混在一起,是手搓 vector 时最常见的 bug:在未初始化的槽位上读 T,或者 reserve 时去默认构造 T(于是不支持“没有默认构造的 T”)。

这一步不用改作业纸

起步页保存的 student/mini_vector/vector.hpp 已经包含 三个字段、empty / size / capacity / data,以及默认构造。不要把下面的示意再贴进 class 体内,否则会重复定义、编译失败。

作业纸现在长这样(只需确认,不要复制):

T*        data_{nullptr};
size_type size_{0};
size_type capacity_{0};
[[no_unique_address]] Allocator alloc_{};
 
Vector() noexcept(std::is_nothrow_default_constructible_v<Allocator>) = default;
explicit Vector(const Allocator& alloc) noexcept : alloc_(alloc) {}
 
[[nodiscard]] bool empty() const noexcept { return size_ == 0; }
size_type          size() const noexcept { return size_; }
size_type          capacity() const noexcept { return capacity_; }
T*                 data() noexcept { return data_; }
const T*           data() const noexcept { return data_; }

默认构造之后:empty() == true,size() == 0,capacity() == 0,data() == nullptr。还没向操作系统要过任何内存。

Vector(n)、Vector(n, value)、initializer_list 构造函数先留着 TODO,Step 06 再填。现在填它们会调用还没写的 allocate_n。

为什么 iterator 直接用 T*

教学实现够用了:vector 的迭代器本就是随机访问,指针满足 begin() + n、end() - begin() 这些接口。标准库用 class iterator 是为了调试时抓越界、以及 fancy pointer。下一步会接到 allocator,但存储仍按 T* 处理(用 std::to_address 把分配器返回的 pointer 转成裸指针)。

作业纸里 begin / end / operator[] 也已经写好。空 vector 时 data_ 是 nullptr,begin() == end() == nullptr,范围 for 不会解引用。

怎么粘贴(后面每步都一样)

作业纸分两截:

  1. 上半 class Vector { ... };:只有声明。除了 Step 07 要给拷贝操作补 requires(作业纸已写好)之外,不要往 class 里面塞函数体。
  2. 下半 template <typename T, typename Allocator> ... Vector<T, Allocator>::foo(...):每个 TODO 对应一个完整函数。用教学站给出的整段(从 template 到函数最后的 })替换那个函数,不要只贴函数体、也不要漏掉 template 头。

搜索标记:TODO(step 02)、TODO(step 03) ……

验收

先按起步页配好工程(学生开关打开),然后:

cmake --build build
./build/vector_tests --gtest_filter='Step01.EmptyVectorHasZeroSizeAndCapacity'

这一条现在就该绿。CountConstructor、Vector(n) 那些要等到 Step 03 / 06。

本步验收

cmake --build build
./build/vector_tests --gtest_filter='Step01*'