news 2026/4/15 15:20:34

【std::vector】vector<T*>与vector<T>*

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【std::vector】vector<T*>与vector<T>*

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录

      • 一、先回答第一个问题:`vector<int*>` 类型拷贝前,是否需要遍历一遍元素 `delete`?
        • 1. 核心前提:`vector<int*>` 只存指针,不管理指针指向的内存(浅拷贝特性)
        • 2. 分情况讨论:是否需要`delete`
          • 情况1:指针指向**栈内存**(或全局/静态内存)
          • 情况2:指针指向**堆内存**(`new int/ new int[]`分配的)
        • 3. 优化方案:用智能指针代替裸指针(推荐)
      • 二、`vector<int*>` 与 `vector<int>*` 的对比
        • 1. 栈堆分布:分层拆解(关键:区分“对象本身”和“对象指向/存储的内容”)
          • (1)`vector<int*>` 的栈堆分布(三层结构)
          • (2)`vector<int>*` 的栈堆分布(三层结构)
        • 2. 适用场景
          • (1)`vector<int*>` 的使用场景
          • (2)`vector<int>*` 的使用场景
        • 3. 核心区别总结
      • 三、补充示例代码
        • 1. `vector<int*>` 的内存管理示例(裸指针版,需手动delete)
        • 2. `vector<int>*` 的示例(现代C++推荐用unique_ptr)

一、先回答第一个问题:vector<int*>类型拷贝前,是否需要遍历一遍元素delete

结论:不一定,核心取决于vector<int*>中存储的指针指向的内存类型,以及谁是这些内存的所有者

1. 核心前提:vector<int*>只存指针,不管理指针指向的内存(浅拷贝特性)

vector<int*>中的元素是**int*类型的指针**,vector的赋值/拷贝操作只会做浅拷贝:即只复制指针的(也就是内存地址),不会复制指针指向的int对象,也不会自动管理指针指向的内存。

因此,vector的默认行为不会帮你delete指针指向的内存——这部分内存的生命周期需要程序员手动控制。

2. 分情况讨论:是否需要delete
情况1:指针指向栈内存(或全局/静态内存)

如果vector<int*>中的指针指向栈上的int(比如int a = 10; int* p = &a;),绝对不能delete
栈内存由编译器自动管理,delete栈指针会导致未定义行为(程序崩溃、内存错乱等)。

情况2:指针指向堆内存new int/ new int[]分配的)

如果指针是通过new/new[]分配的堆内存(比如int* p = new int(5);),则需要分场景:

  • 场景A:当前vector是该堆内存的唯一所有者(没有其他指针指向这块内存):
    在拷贝(赋值、清空、析构)前,必须遍历vector执行delete(或delete[],否则指针指向的堆内存会成为“孤儿内存”,导致内存泄漏
  • 场景B:堆内存被多个指针共享(比如其他变量也指向这块内存):
    不能直接delete,否则会导致其他指针变成悬垂指针(指向已释放的内存),后续访问会触发未定义行为。
3. 优化方案:用智能指针代替裸指针(推荐)

手动delete裸指针容易出错(漏删、重复删、删栈指针),C++11起推荐用智能指针unique_ptr/shared_ptr)代替裸指针,智能指针会自动管理内存,无需手动delete

// 用unique_ptr(独占所有权)代替裸指针,自动释放内存vector<unique_ptr<int>>v1;v1.push_back(make_unique<int>(5));v1.push_back(make_unique<int>(6));// 赋值时,unique_ptr会自动转移所有权,旧的unique_ptr会自动释放内存(无需手动delete)vector<unique_ptr<int>>v2;v1=v2;// 旧的v1元素(unique_ptr)会被销毁,自动delete指向的int

二、vector<int*>vector<int>*的对比

首先明确两者的类型本质,这是理解后续内容的关键:

类型本质含义
vector<int*>一个vector容器对象,其存储的元素是int*类型的指针(指向int的指针)
vector<int>*一个指针变量,其指向的是vector<int>类型的容器对象

接下来从栈堆分布使用场景核心区别三个维度详细分析。

1. 栈堆分布:分层拆解(关键:区分“对象本身”和“对象指向/存储的内容”)

C++中内存分布的核心规则:局部变量(非static)在栈上,new/malloc分配的在堆上。但vector的底层特性是:无论vector对象本身在栈还是堆,其内部存储的元素数组永远在堆上(vector的动态数组是动态分配的)。

(1)vector<int*>的栈堆分布(三层结构)
  • 第一层:vector<int*>对象本身
    取决于声明方式:
    • 局部变量:vector<int*> v;→ 对象本身在上(栈帧中)。
    • 动态分配:vector<int*> *pv = new vector<int*>;→ 对象本身在上(new分配)。
  • 第二层:vector<int*>内部的元素数组(存储int*指针的数组)
    无论vector对象本身在栈还是堆,这部分数组永远在上(vector的底层实现决定)。
  • 第三层:int*指针指向的int对象
    由指针的赋值决定:
    • 指向栈:int a = 10; int* p = &a;int在栈上。
    • 指向堆:int* p = new int(10);int在堆上。
(2)vector<int>*的栈堆分布(三层结构)
  • 第一层:vector<int>*指针变量本身
    取决于声明方式:
    • 局部变量:vector<int>* pv;→ 指针变量本身在上(栈帧中,占用8字节(64位)存储内存地址)。
    • 动态分配:vector<int>** ppv = new vector<int>*;→ 指针变量本身在上(极少用)。
  • 第二层:指针指向的vector<int>对象
    几乎只能在堆上(否则无意义,且易出错):
    • 正确用法:pv = new vector<int>;vector<int>对象在堆上。
    • 错误用法:vector<int> v; pv = &v;pv指向栈上的vector,若v先销毁,pv会变成悬垂指针(后续访问崩溃)。
  • 第三层:vector<int>对象内部的int元素数组
    永远在上(vector的底层特性)。
2. 适用场景
(1)vector<int*>的使用场景

用于需要存储多个指向int的指针的场景,常见情况:

  • 场景1:管理一组独立的动态int对象/数组
    比如需要存储多个大小不同的int数组(int* arr1 = new int[5]; int* arr2 = new int[10];),可以用vector<int*>存储这些数组的首地址。
  • 场景2:与C风格代码交互
    C函数常返回int*类型的数组(如int* get_data()),可以用vector<int*>接收和管理这些指针。
  • 场景3:存储指向不同内存位置的int
    比如同时指向栈上的int、全局int、堆上的int

注意:尽量用vector<unique_ptr<int>>/vector<shared_ptr<int>>代替裸指针的vector<int*>,避免手动管理内存的风险。

(2)vector<int>*的使用场景

这种用法在现代C++中逐渐减少,仅在特定场景下使用:

  • 场景1:大型vector对象,避免栈溢出
    栈空间有限(通常几MB),如果要创建存储百万级intvector<int>,直接在栈上声明(vector<int> v(1000000);)会导致栈溢出,此时可以用vector<int>* pv = new vector<int>(1000000);(将vector对象放在堆上)。
  • 场景2:动态控制vector的生命周期
    比如需要让vector对象的生命周期跨越函数调用(如作为全局指针,在函数中创建,程序结束时销毁),或根据条件动态创建/销毁vector
  • 场景3:旧代码中作为函数参数传递(现代C++不推荐)
    早期C++中,为了避免函数参数传递vector时的拷贝开销,会用vector<int>*传递指针;但现代C++推荐用引用(vector<int>&const引用(const vector<int>&,效率更高且更安全。

注意:vector<int>*的裸指针容易出现忘记delete(内存泄漏)或悬垂指针(访问崩溃),现代C++推荐用unique_ptr<vector<int>>(独占所有权)或shared_ptr<vector<int>>(共享所有权)代替。

3. 核心区别总结
维度vector<int*>vector<int>*
类型本质vector容器(存储int*指针)指针(指向vector<int>容器)
存储的核心内容多个int*指针(地址)一个vector<int>容器的地址
内存泄漏风险点裸指针指向的堆内存未delete指向的vector<int>对象未delete
现代C++替代方案vector<unique_ptr<int>>/shared_ptr<int>unique_ptr<vector<int>>/shared_ptr<vector<int>>
常用程度偶尔用(需指针场景)极少用(现代C++推荐引用/移动语义)

三、补充示例代码

1.vector<int*>的内存管理示例(裸指针版,需手动delete)
#include<iostream>#include<vector>usingnamespacestd;intmain(){vector<int*>v1;// 向v1中添加堆内存的int指针v1.push_back(newint(1));v1.push_back(newint(2));// 拷贝前:遍历delete原有元素(避免内存泄漏)for(int*p:v1){deletep;// 释放指针指向的堆内存}v1.clear();// 清空vector中的指针(可选,赋值时会自动销毁原有元素)// 赋值新的vector<int*>vector<int*>v2;v2.push_back(newint(5));v1=v2;// 程序结束前:再次遍历delete v1中的元素for(int*p:v1){deletep;}return0;}
2.vector<int>*的示例(现代C++推荐用unique_ptr)
#include<iostream>#include<vector>#include<memory>// 智能指针头文件usingnamespacestd;intmain(){// 旧写法:裸指针,需手动deletevector<int>*pv1=newvector<int>{1,2,3};cout<<pv1->size()<<endl;// 访问vector的成员需用->deletepv1;// 必须delete,否则内存泄漏// 现代C++写法:unique_ptr,自动释放unique_ptr<vector<int>>pv2=make_unique<vector<int>>({4,5,6});cout<<pv2->size()<<endl;// 无需delete,unique_ptr析构时自动释放vector对象return0;}
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/11 15:32:18

e1547:开源免费的e621社区移动端解决方案完全指南

e1547&#xff1a;开源免费的e621社区移动端解决方案完全指南 【免费下载链接】e1547 A sophisticated e621 browser 项目地址: https://gitcode.com/gh_mirrors/e1/e1547 e1547是一款基于Flutter框架开发的高级e621社区浏览器&#xff0c;为移动设备用户提供专业级的内…

作者头像 李华
网站建设 2026/4/8 2:42:26

【std::vector】数据内存分配

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录一、先明确&#xff1a;vector的底层实现原理二、分层拆解&#xff1a;vector<int> v的内存分布其他声明方式的vector对象&#xff0c;元素数组仍在堆上三、为…

作者头像 李华
网站建设 2026/4/2 2:36:32

彻底告别消息丢失!PC端微信QQ防撤回技术完全指南

彻底告别消息丢失&#xff01;PC端微信QQ防撤回技术完全指南 【免费下载链接】RevokeMsgPatcher :trollface: A hex editor for WeChat/QQ/TIM - PC版微信/QQ/TIM防撤回补丁&#xff08;我已经看到了&#xff0c;撤回也没用了&#xff09; 项目地址: https://gitcode.com/Git…

作者头像 李华
网站建设 2026/4/10 8:13:25

PKHeX自动化合法性插件:5分钟快速生成100%合法宝可梦的终极方案

PKHeX自动化合法性插件&#xff1a;5分钟快速生成100%合法宝可梦的终极方案 【免费下载链接】PKHeX-Plugins Plugins for PKHeX 项目地址: https://gitcode.com/gh_mirrors/pk/PKHeX-Plugins 还在为宝可梦数据合法性检查而烦恼吗&#xff1f;PKHeX-Plugins项目的AutoLeg…

作者头像 李华
网站建设 2026/4/15 9:34:44

ImageToSTL:从平面图像到立体模型的魔法转换器

ImageToSTL&#xff1a;从平面图像到立体模型的魔法转换器 【免费下载链接】ImageToSTL This tool allows you to easily convert any image into a 3D print-ready STL model. The surface of the model will display the image when illuminated from the left side. 项目地…

作者头像 李华