C++动态指针和动态数组,基础详解
文章目录
前言
学习C++的过程中,动态数组是绕不开的核心知识点。很多同学一开始会混淆静态数组、动态数组,也搞不懂底层原理和以及其法,这篇文章就顺着学习思路,从零开始,一步步吃透动态数组,从普通手写,到vector底层,再到智能指针进阶,全程干货,保证轻松看懂。
一、先分清:静态数组VS动态数组
静态数组
编译时就确定大小,内存开辟在栈区,大小固定不可修改。
// 大小固定为5,不能更改
int arr[5];
优点:写法简单,速度快;缺点:不够灵活,无法扩容,栈区空间有限。
动态数组
运行时确定大小,内存开辟在堆区,大小可灵活调整,能按需扩容。
优点:灵活通用,适合未知数据量的场景;缺点:手动写法需要管理内存,容易出现内存泄漏。
二、基础写法:用普通指针来实现动态数组
1.核心步骤
- 定义指针,指向堆区开辟的内存
- 赋值、访问、遍历,用法和普通数组一致
- 手动扩容(申请新空间→拷贝数据→释放旧空间)
- 用完释放内存,避免内存泄漏
#include <iostream>
using namespace std;
int main() {
// 1. 定义数组大小,开辟堆内存
int size = 5;
int* arr = new int[size];
// 2. 赋值
for (int i = 0; i < size; i++) {
arr[i] = i + 1;
}
// 3. 遍历访问
for (int i = 0; i < size; i++) {
cout << arr[i] << " ";
}
cout << endl;
// 4. 手动扩容示例
int newSize = size * 2;
int* newArr = new int[newSize];
// 拷贝旧数据
for (int i = 0; i < size; i++) {
newArr[i] = arr[i];
}
// 释放旧空间,指针指向新空间
delete[] arr;
arr = newArr;
newArr = nullptr;
size = newSize;
// 5. 最终释放内存,指针置空
delete[] arr;
arr = nullptr;
return 0;
}
重点:new[] 必须搭配 delete[],少了括号会导致内存泄漏;释放后指针置空,防止野指针。
三、进阶底层:vector三指针模型
平时用的vector(STL),就是封装好的动态数组,不用手动管理内存,它的底层靠三指针实现内存管理,也是面试高频考点。
3.1三个核心指针
start:指向数组起始地址
finish:指向最后一个有效元素的下一位
end_of_storage:指向整个内存空间的末尾
关键概念
size(元素个数):finish - start
capacity(总容量):end_of_storage - start
当元素个数等于容量时,vector会自动扩容(通常扩容1.5倍或2倍),全程不用手动操作,安全省心。
其基本的操作逻辑如下:
3.2vector常用操作
| 操作 | 代码 | 作用 |
|---|---|---|
| 尾部添加 | v.push_back(x) |
末尾插入元素,自动扩容 |
| 尾部删除 | v.pop_back() |
删除最后一个元素 |
| 获取个数 | v.size() |
返回有效元素数量 |
| 指定位置插入 | v.insert(pos, x) |
在指定位置插入元素 |
| 删除指定元素 | v.erase(pos) |
删除指定位置元素 |
| 清空数组 | v.clear() |
清空所有元素,不释放空间 |
四、智能指针管理动态数组
普通指针需要手动释放内存,很容易忘记写delete[],造成内存泄漏。C++提供了智能指针,能自动释放内存,兼顾底层灵活性和安全性。
核心注意事项
管理动态数组,必须用 unique_ptr<T[]>(带方括号),普通unique_ptr会调用delete,而不是delete[],会导致程序出错。
标准写法:
#include <iostream>
#include <memory> // 智能指针必备头文件
using namespace std;
int main() {
// 1. 创建智能指针管理的动态数组(C++14及以上推荐)
auto arr = make_unique<int[]>(5);
// 2. 赋值、访问,和普通数组用法完全一样
arr[0] = 10;
arr[1] = 20;
arr[2] = 30;
// 3. 遍历
for (int i = 0; i < 5; i++) {
cout << arr[i] << " ";
}
// 4. 无需手动delete[],离开作用域自动释放
return 0;
}
拓展:
unique_ptr<ClassRoom[]> 和 unique_ptr<unique_ptr[]> 有什么区别,该怎么选?
普通智能指针数组
unique_ptr<ClassRoom[]> arr;
特点:数组直接存放对象,内存连续,写法简单,速度快,自动创建和销毁对象。
适用场景:单纯存储对象数据,不需要多态,不需要空指针,普通业务场景首选。
嵌套智能指针数组
unique_ptr<unique_ptr[]> arr;
特点:数组存放指针,不直接存对象,支持空指针,支持多态(父类指针指向子类)。
适用场景:对象体积大,避免拷贝;需要用到继承多态;数组元素需要置空的场景。
总结
- 静态数组大小固定,动态数组运行时可调整,存于堆区
- 普通指针实现动态数组,必须new[]搭配delete[],防止内存泄漏
- vector底层是三指针模型,自动扩容自动释放,日常开发首选
- 智能指针版动态数组用unique_ptr<T[]>,兼顾底层和安全,不用手动释放
- 普通场景用普通智能指针数组,多态/大对象场景用嵌套写法
- 模板能实现万能动态数组,适配所有数据类型
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)