商城首页欢迎来到中国正版软件门户

您的位置: 首页 > 文章列表 > 编程开发 > C++实现简单的动态数组 _ 手写Vector底层扩容逻辑【源码】

C++实现简单的动态数组 _ 手写Vector底层扩容逻辑【源码】

  发布于2026-07-19 阅读(0)

扫一扫,手机访问

扩容必须分配新内存并逐个移动/拷贝构造,因为vector底层是连续原始缓冲区,new[]没办法就地延展,realloc对非平凡类型也不适用。直接拿memcpy去拷string这类带指针、引用计数的对象,结果就是双释放或悬垂指针。

C++实现简单的动态数组 _ 手写Vector底层扩容逻辑【源码】

扩容时为什么必须用 malloc + memcpynew + 手动拷贝?

关键原因在于 std::vector 的内存是连续原始缓冲区,没有“就地扩容”这个选项。C++ 的 new[] 分配的是固定大小的堆块,不像 realloc 还能尝试原地延展(而且 realloc 对含有非平凡构造函数的对象根本行不通)。所以唯一安全的路径是:分配新内存 → 逐个调用移动/拷贝构造 → 析构旧对象 → 释放旧内存。

不少人图省事,直接 memcpy 原始字节——对 int 这种平凡类型没毛病,但一旦碰上 std::string 这类内部带指针、引用计数的对象,就会引发双释放或悬垂指针,调试起来非常头疼。

  • 正确做法:对每个旧元素调用 T(std::move(old[i]))T(old[i]) 构造到新地址
  • 必须用 std::allocator_traits::construct 或手动调用构造函数,不能跳过
  • 旧元素析构前,必须确保新位置已构造完成,否则异常安全难保证

push_back 触发扩容时,如何避免重复计算容量?

每次 push_back 都检查 size_ == capacity_ 是必须的,但扩容倍数策略直接影响性能。用固定加法(比如每次+1)会导致 O(n²) 复杂度,用乘性增长(如 ×1.5 或 ×2)才能摊还为 O(1)。

注意:×2 简单但可能浪费内存;×1.5 更省空间,不过需要浮点运算或整数技巧(比如 new_cap = size_ + size_ / 2)。实际中 std::vector 通常用 ×2。

  • 扩容前先算好 new_capacity,不要在循环里反复计算
  • 首次分配建议设为 1 或 2,避免空 vector 也 malloc 一次
  • 如果传入初始 n,直接分配 n 容量,别先分配 0 再 push n 次

怎么安全处理 T 是 move-only 类型(如 std::unique_ptr)?

手写 vector 必须区分 T 是否支持移动。如果只用 copy,对 unique_ptr 编译不过;如果盲目用 move,对 int 虽无害但冗余。标准做法是优先 move,fallback 到 copy。

核心是用 std::is_nothrow_move_constructible_vstd::is_copy_constructible_v 做 trait 判断,再配合 std::movestatic_cast

  • 构造新元素时:用 new (ptr) T(std::move(old_elem)),不是 new (ptr) T(old_elem)
  • 旧元素析构前,必须先完成所有新元素构造,否则异常发生时状态不一致
  • 别忘了在析构函数里对 [0, size_) 区间内每个元素显式调用 obj.~T()

为什么不能直接继承 std::allocator 来管理内存?

继承是可以继承,但没必要,而且容易误用。std::allocator 只负责 raw 内存分配/释放(allocate/deallocate),不负责对象构造/析构。真正要复用的是它的接口约定,而不是继承它。

更轻量、更可控的做法是封装一个 allocator_type 类型别名,默认用 std::allocator,并在内部调用 alloc_.allocate(n)alloc_.deallocate(ptr, n)

  • 自己 new/delete 容易漏掉对齐要求(尤其 C++17 后 operator new 支持对齐参数)
  • std::allocator 可无缝对接自定义 allocator(比如 arena allocator)
  • 别在类里硬编码 sizeof(T) —— 让 allocator 自己算

真实手写时最常被忽略的,是异常安全边界:只要新内存分配成功,但某个元素构造抛异常,就必须立即析构已构造的新元素,并释放新内存,然后重新抛出——这个 try-catch 块不能少,也不能只包构造不包析构。

本文转载于:https://www.php.cn/faq/2313336.html 如有侵犯,请联系zhengruancom@outlook.com删除。
免责声明:正软商城发布此文仅为传递信息,不代表正软商城认同其观点或证实其描述。

热门关注