news 2026/10/15 15:49:03

【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),如果要创建存储百万级int的vector<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/10/12 11:13:46

Vue 3后台管理系统实战宝典:Element Plus Admin高效开发全攻略

Vue 3后台管理系统实战宝典&#xff1a;Element Plus Admin高效开发全攻略 【免费下载链接】element-plus-admin 基于vitetselementPlus 项目地址: https://gitcode.com/gh_mirrors/el/element-plus-admin 想要快速搭建一个专业的企业级后台管理系统吗&#xff1f;基于V…

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

NomNom:No Man‘s Sky存档编辑器的技术实现与应用指南

NomNom&#xff1a;No Mans Sky存档编辑器的技术实现与应用指南 【免费下载链接】NomNom NomNom is the most complete savegame editor for NMS but also shows additional information around the data youre about to change. You can also easily look up each item indivi…

作者头像 李华
网站建设 2026/10/13 12:31:32

Harepacker复活版:MapleStory游戏资源的终极编辑神器

Harepacker复活版&#xff1a;MapleStory游戏资源的终极编辑神器 【免费下载链接】Harepacker-resurrected All in one .wz file/map editor for MapleStory game files 项目地址: https://gitcode.com/gh_mirrors/ha/Harepacker-resurrected 在游戏开发与修改的世界里&…

作者头像 李华
网站建设 2026/10/15 7:53:48

TouchGal:Galgame爱好者的终极社区体验完整指南

TouchGal&#xff1a;Galgame爱好者的终极社区体验完整指南 【免费下载链接】kun-touchgal-next TouchGAL是立足于分享快乐的一站式Galgame文化社区, 为Gal爱好者提供一片净土! 项目地址: https://gitcode.com/gh_mirrors/ku/kun-touchgal-next 在当前数字时代&#xff…

作者头像 李华
网站建设 2026/10/15 10:24:38

PDF-Extract-Kit技巧:提高表格结构识别准确率

PDF-Extract-Kit技巧&#xff1a;提高表格结构识别准确率 1. 背景与挑战&#xff1a;PDF表格提取的痛点 在科研、金融、法律等领域的文档处理中&#xff0c;PDF格式因其版式固定、跨平台兼容性强而被广泛使用。然而&#xff0c;当需要将PDF中的信息数字化时&#xff0c;尤其是…

作者头像 李华
网站建设 2026/10/11 0:16:40

PDF-Extract-Kit设计理念:解决的核心问题

PDF-Extract-Kit设计理念&#xff1a;解决的核心问题 1. 背景与核心挑战 1.1 PDF文档处理的行业痛点 在科研、教育、出版和企业办公等领域&#xff0c;PDF作为最通用的文档格式之一&#xff0c;承载了大量结构化与非结构化的信息。然而&#xff0c;尽管PDF在跨平台展示上具有…

作者头像 李华