0

0

C++如何实现动态数组?(类似std::vector的简易版)

穿越時空

穿越時空

发布时间:2026-03-11 17:27:32

|

256人浏览过

|

来源于php中文网

原创

手动管理内存实现动态数组需用new/delete[]配合裸指针,维护m_data、m_size、m_capacity三个成员,扩容时用2倍策略、移动构造、显式析构,注意对齐与noexcept。

c++如何实现动态数组?(类似std::vector的简易版)

怎么手动管理内存实现动态数组

直接用 newdelete[] 配合裸指针是最底层的方式,但必须自己管容量、大小、扩容逻辑。不是不能写,而是稍有疏忽就会内存泄漏或越界——比如忘了在拷贝构造里深拷贝,或者 resize 时没正确释放旧内存。

实操建议:

  • 用两个成员变量:m_dataT* 指针)和 m_size(当前元素个数),再加一个 m_capacity(已分配空间大小)
  • 首次分配建议设容量为 1 或 2,别从 0 开始;否则每次 push_back 都要 realloc,性能极差
  • push_back 前必须检查 m_size == m_capacity,触发扩容:通常用 m_capacity * 2,别用 +1(摊还成本爆炸)
  • 扩容时先 new T[new_capacity],逐个调用 new (&dest[i]) T(std::move(src[i])) 移动构造(C++11+),再显式调用旧对象的析构函数,最后 delete[] m_data

为什么不能直接用 std::vector 的部分源码来简化

因为 std::vector 依赖 std::allocatorstd::uninitialized_copy 等设施,还做了异常安全、SFINAE、迭代器类别等大量适配。抄几行 data_size_ 看似简单,但一旦涉及异常(比如构造函数抛出)、移动语义或自定义类型,裸指针方案立刻崩。

常见错误现象:

立即学习C++免费学习笔记(深入)”;

  • 插入含资源的对象(如 std::string)时,只做位拷贝(memcpy),导致多个对象指向同一堆内存,析构时报 double-free
  • 没声明移动构造/移动赋值,对象在 vector 扩容时被反复拷贝,性能陡降且可能失败
  • 没处理 noexcept,导致 std::vector 在某些优化路径下拒绝移动而改用拷贝

简易版该暴露哪些接口才够用

够用 ≠ 全,重点是让使用者不掉坑。比如 operator[] 不做边界检查(和 std::vector::operator[] 一致),但必须提供 at() 做带异常的访问——否则调试时根本不知道哪越界了。

纳米漫剧流水线
纳米漫剧流水线

360推出的国内首个工业级AI漫剧生产平台

下载

实操建议:

  • 必有:构造函数(空、带初始容量)、push_back(const T&)push_back(T&&)size()capacity()empty()operator[]at()pop_back()、析构函数
  • 可选但推荐:reserve()(预分配,避免多次扩容)、clear()(只清 size,不释放内存)、移动构造/赋值(用 noexcept 标记)
  • 别急着加 insert / erase —— 它们需要迭代器支持,一写就牵扯到 traits、tag dispatch、std::distance,复杂度指数上升

容易被忽略的细节:对齐与 noexcept

如果存的是 alignas(16) 类型(比如 SIMD 结构体),仅用 new char[capacity * sizeof(T)] 分配内存会导致地址不对齐,触发硬件异常。而 std::allocator 内部会调用 std::align 修正。

另一个隐形炸弹是 noexcept:哪怕你所有操作都不抛异常,只要没显式写 noexcept,编译器就默认函数可能抛,导致 std::vector 在 move-aware 容器中退化成拷贝。

所以:

  • 手动分配内存时,用 operator new(size, std::align_val_t{alignof(T)}) 替代裸 new char[]
  • 所有不抛异常的函数(构造、移动、push_back 等)末尾加上 noexcept
  • 移动操作里,确保 T 的移动构造/赋值也是 noexcept,否则你的移动函数会被视为可能抛异常

这些点不写代码时看不出问题,一跑 ASan 或上生产环境就卡住半天——尤其对齐问题,在 x86 可能只是慢,在 ARM 直接 crash。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

1010

2023.08.02

c语言const用法
c语言const用法

const是关键字,可以用于声明常量、函数参数中的const修饰符、const修饰函数返回值、const修饰指针。详细介绍:1、声明常量,const关键字可用于声明常量,常量的值在程序运行期间不可修改,常量可以是基本数据类型,如整数、浮点数、字符等,也可是自定义的数据类型;2、函数参数中的const修饰符,const关键字可用于函数的参数中,表示该参数在函数内部不可修改等等。

562

2023.09.20

golang结构体相关大全
golang结构体相关大全

本专题整合了golang结构体相关大全,想了解更多内容,请阅读专题下面的文章。

490

2025.06.09

golang结构体方法
golang结构体方法

本专题整合了golang结构体相关内容,请阅读专题下面的文章了解更多。

202

2025.07.04

c++怎么把double转成int
c++怎么把double转成int

本专题整合了 c++ double相关教程,阅读专题下面的文章了解更多详细内容。

334

2025.08.29

C++中int、float和double的区别
C++中int、float和double的区别

本专题整合了c++中int和double的区别,阅读专题下面的文章了解更多详细内容。

105

2025.10.23

硬盘接口类型介绍
硬盘接口类型介绍

硬盘接口类型有IDE、SATA、SCSI、Fibre Channel、USB、eSATA、mSATA、PCIe等等。详细介绍:1、IDE接口是一种并行接口,主要用于连接硬盘和光驱等设备,它主要有两种类型:ATA和ATAPI,IDE接口已经逐渐被SATA接口;2、SATA接口是一种串行接口,相较于IDE接口,它具有更高的传输速度、更低的功耗和更小的体积;3、SCSI接口等等。

1902

2023.10.19

PHP接口编写教程
PHP接口编写教程

本专题整合了PHP接口编写教程,阅读专题下面的文章了解更多详细内容。

656

2025.10.17

C# ASP.NET Core微服务架构与API网关实践
C# ASP.NET Core微服务架构与API网关实践

本专题围绕 C# 在现代后端架构中的微服务实践展开,系统讲解基于 ASP.NET Core 构建可扩展服务体系的核心方法。内容涵盖服务拆分策略、RESTful API 设计、服务间通信、API 网关统一入口管理以及服务治理机制。通过真实项目案例,帮助开发者掌握构建高可用微服务系统的关键技术,提高系统的可扩展性与维护效率。

3

2026.03.11

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C# 教程
C# 教程

共94课时 | 11.1万人学习

C 教程
C 教程

共75课时 | 5.3万人学习

C++教程
C++教程

共115课时 | 21.4万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号