当前位置: 首页 > news >正文

C++动态数组两种实现方式详解(std::vector vs malloc)

在C中动态数组是处理可变大小数据集合的常见需求。本文将详细介绍两种主要的实现方式使用C标准库的std::vector和使用C风格的malloc并对比它们的差异、使用方法以及最佳实践。1. std::vector现代C的推荐方式1.1 基本语法与参数12345// 基本语法std::vectorT name(size);// 实际示例std::vectoruint8_t occlusions(points_cnt);参数详解模板参数T指定向量中元素的类型这里是uint8_t无符号8位整数通常就是unsigned char构造函数参数size指定向量初始的大小这里是points_cnt必须是整数类型向量名称occlusions变量名遵循C命名规则1.2 如何访问和操作元素访问单个元素1234567891011// 使用下标运算符不进行边界检查occlusions[0] 255;// 设置第一个元素uint8_t value occlusions[0];// 获取第一个元素// 使用at()方法进行边界检查安全但稍慢occlusions.at(0) 255;// 如果索引越界会抛出std::out_of_range异常uint8_t value occlusions.at(0);// 使用迭代器auto it occlusions.begin();// 获取起始迭代器*it 255;// 通过迭代器访问元素遍历所有元素123456789101112131415// 方法1使用下标循环for(size_ti 0; i occlusions.size(); i) {occlusions[i] i % 256;// 赋值std::cout (int)occlusions[i] ;// 访问}// 方法2使用范围for循环C11起for(uint8_t val : occlusions) {val 128;// 可以直接修改}// 方法3使用迭代器for(auto it occlusions.begin(); it ! occlusions.end(); it) {*it 64;}1.3 完整示例123456789101112131415161718192021222324252627282930313233#include iostream#include vector#include cstdintvoidvectorExample() {size_tpoints_cnt 10;// 创建并初始化向量std::vectoruint8_t occlusions(points_cnt, 0);// 所有元素初始化为0// 修改元素for(size_ti 0; i points_cnt; i) {occlusions[i] static_castuint8_t(i * 25);}// 添加新元素occlusions.push_back(255);// 自动调整大小occlusions.emplace_back(128);// C11原地构造// 读取并显示所有元素std::cout Vector contents: ;for(constauto val : occlusions) {std::cout (int)val ;}std::cout std::endl;// 获取向量信息std::cout Size: occlusions.size() std::endl;std::cout Capacity: occlusions.capacity() std::endl;// 注意不需要手动释放内存// 当occlusions离开作用域时vector会自动清理}2. mallocC风格的动态内存分配2.1 基本语法与参数12345// 基本语法T* name (T*)malloc(count *sizeof(T));// 实际示例unsignedchar* occlusions (unsignedchar*)malloc(points_cnt *sizeof(unsignedchar));参数详解malloc函数参数需要分配的字节数 points_cnt * sizeof(unsigned char)返回值类型转换malloc返回void*需要强制转换为目标指针类型指针变量occlusions指向分配内存起始地址的指针2.2 如何访问和操作元素访问单个元素12345678// 使用数组下标语法occlusions[0] 255;// 设置第一个元素unsignedcharvalue occlusions[0];// 获取第一个元素// 使用指针算术*(occlusions) 255;// 等价于occlusions[0] 255*(occlusions 1) 128;// 等价于occlusions[1] 128unsignedcharvalue *(occlusions 2);// 等价于occlusions[2]遍历所有元素1234567891011// 使用指针遍历unsignedchar* ptr occlusions;for(size_ti 0; i points_cnt; i) {*ptr static_castunsignedchar(i * 25);ptr;// 移动指针}// 使用下标遍历for(size_ti 0; i points_cnt; i) {occlusions[i] i % 256;}2.3 完整示例123456789101112131415161718192021222324252627282930313233343536#include iostream#include cstdlib // malloc, free#include cstring // memsetvoidmallocExample() {size_tpoints_cnt 10;// 分配内存unsignedchar* occlusions (unsignedchar*)malloc(points_cnt *sizeof(unsignedchar));// 重要检查分配是否成功if(occlusions nullptr) {std::cerr Memory allocation failed! std::endl;return;}// 重要初始化内存malloc不初始化内存memset(occlusions, 0, points_cnt *sizeof(unsignedchar));// 填充数据for(size_ti 0; i points_cnt; i) {occlusions[i] static_castunsignedchar(i * 25);}// 显示内容std::cout Malloc array contents: ;for(size_ti 0; i points_cnt; i) {std::cout (int)occlusions[i] ;}std::cout std::endl;// 重要必须手动释放内存free(occlusions);occlusions nullptr;// 避免野指针}3. 详细对比与选择指南3.1 内存管理对比特性std::vectormalloc/free初始化默认初始化元素不初始化内容是随机的内存释放自动RAII必须手动调用free()异常安全是构造函数失败会抛出异常否需要检查返回值重新分配自动resize/push_back需要realloc()数据可能被移动3.2 性能与安全对比1234567891011121314151617181920212223242526272829// std::vector的安全性示例voidsafeVectorExample() {std::vectoruint8_t vec(10);try{vec.at(20) 100;// 抛出std::out_of_range异常}catch(conststd::out_of_range e) {std::cout 安全地捕获了越界访问: e.what() std::endl;}// vec[20] 100; // 未定义行为可能崩溃或数据损坏}// malloc的不安全性示例voidunsafeMallocExample() {unsignedchar* arr (unsignedchar*)malloc(10);// 常见错误1忘记检查分配是否成功if(arr nullptr) {/* 必须检查 */}// 常见错误2忘记初始化// arr[0]可能是任意值// 常见错误3越界访问arr[15] 100;// 未定义行为可能破坏其他内存// 常见错误4忘记释放内存内存泄漏// free(arr); // 如果忘记这行内存泄漏}4. 高级用法与技巧4.1 std::vector的高级特性12345678910111213141516171819202122voidadvancedVectorUsage() {// 多种初始化方式std::vectoruint8_t v1(10, 0xFF);// 10个元素每个都是0xFFstd::vectoruint8_t v2 {0, 1, 2, 3, 4};// 初始化列表C11std::vectoruint8_t v3(v1);// 拷贝构造// 内存预分配v1.reserve(1000);// 预分配内存避免多次重新分配// 安全访问if(!v1.empty()) {uint8_t first v1.front();// 第一个元素uint8_t last v1.back();// 最后一个元素}// 范围操作v1.insert(v1.begin(), {10, 20, 30});// 开头插入多个元素v1.erase(v1.begin() 1, v1.begin() 3);// 删除第2-3个元素// C17并行算法支持std::sort(std::execution::par, v1.begin(), v1.end());}4.2 malloc的高级用法与陷阱123456789101112131415161718192021222324voidadvancedMallocUsage() {size_tcount 10;// 正确使用calloc自动初始化为0unsignedchar* arr1 (unsignedchar*)malloc(count *sizeof(unsignedchar));// arr1的所有元素都是0// 正确使用realloc调整大小arr1 (unsignedchar*)realloc(arr1, count * 2);// 注意realloc可能移动内存原有指针失效// 陷阱错误的大小计算// 错误可能溢出size_tlarge 1000000000;// unsigned char* bad malloc(large * large); // 溢出// 正确检查溢出if(large SIZE_MAX /sizeof(unsignedchar)) {// 处理溢出错误}// 释放内存free(arr1);}到此这篇关于C动态数组两种实现方式详解(std::vector vs malloc)的文章就介绍到这了,
http://www.zskr.cn/news/1378915.html

相关文章:

  • 024、NPU指令集架构(ISA)概述:从CISC到VLIW
  • RedisDesktopManager Windows版:3分钟掌握免费Redis可视化工具,告别命令行操作!
  • 023、深度可分离卷积:MobileNet背后的计算优化
  • 028、片上SRAM vs 片外DRAM:NPU存储设计的权衡
  • 026、DMA引擎:NPU与外部存储的数据搬运工
  • 单向晶闸管开关电路基础知识及Multisim电路仿真
  • 基于孪生卷积神经网络的星系团速度图相似性度量与匹配
  • Android 深度电量优化实战:聚焦后台任务、Alarm 与 WorkManager 的现代解决方案
  • 如何快速掌握Diablo Edit2:暗黑破坏神2存档修改终极指南
  • m4s-converter:如何在5秒内将B站缓存视频转换为通用MP4格式
  • 沈阳6月雨季来临,房屋漏水怎么办?卫生间免砸砖防水、外墙、屋面+地下室渗漏。权威防水公司靠谱TOP5推荐(2026年6月本地最新深度调研) - 企业资讯
  • 别再手动测Bug了!用Google Gtest 1.14.0给你的C++代码上个“保险”(附完整配置流程)
  • 免费岛屿设计终极指南:5分钟快速掌握Happy Island Designer
  • Python爬虫避坑手册:10年爬取经验总结,看完再也不会被封IP
  • 如何用FGA自动化工具解放双手:5个技巧让FGO刷本效率提升300%
  • 3步掌握UE4SS:从游戏玩家到模组开发者的完整路径
  • 终极Unity游戏去马赛克完整指南:5个免费插件的简单配置教程 [特殊字符]
  • 深度解析yuzu:开源Switch模拟器的架构设计与性能优化指南
  • 【独家披露】DeepSeek灰度发布SLI/SLO基线标准:99.95%可用性背后的4层验证漏斗
  • 免费岛屿设计工具终极指南:Happy Island Designer 完整教程 [特殊字符]️
  • 终极免费方案:Wand-Enhancer 强力解锁WeMod完整功能完整指南
  • 淘金币自动化脚本:5分钟完成淘宝每日任务终极指南
  • 如何轻松让老旧Mac焕发新生:OpenCore Legacy Patcher完整实践指南
  • 开源知识库GitHub使用经验总结
  • 5分钟完成淘宝淘金币全任务:终极自动化脚本使用指南
  • Scroll Reverser:macOS设备级滚动方向控制的技术实现方案
  • 3分钟快速上手:SPT-AKI存档编辑器的终极修改指南
  • 消防宣传展厅设备超级消防员:打造沉浸式互动科普新模式
  • 别再乱用LookRotation了!Unity中控制角色朝向的3个实战技巧与常见误区
  • 如何高效清理Mac磁盘空间:专业工具Pearcleaner使用指南