多级指针本身不分配内存,真正需分配的是其最终指向的数据块;分配方式取决于指针级数、目标结构及内存函数选择,且必须严格配对释放,推荐使用std::vector替代裸指针。

多级指针本身不“分配内存”,真正需要分配的是它最终指向的数据块;分配方式取决于你用的是几级指针、目标数据结构(如字符串数组、二维数组),以及是否用 new 还是 malloc。
char** 动态分配字符串数组时,必须两级分配
常见错误是只分配了指针数组,忘了给每个 char* 指向的字符串单独分配空间。结果一写就崩溃,或者输出乱码。
-
char** names = new char*[n]:只分配了n个char*的数组空间(即存地址的地方),每个元素初始值是未定义的(野指针) - 必须紧接着对每个
names[i]调用new char[size]或malloc(size),否则strcpy(names[i], "xxx")会写入非法地址 - 释放顺序必须相反:先
delete[] names[i](或free(names[i])),再delete[] names(或free(names))
int** 分配动态二维数组,别漏掉中间层
想模拟 int arr[rows][cols] 但大小运行时才知?不能直接 new int[rows * cols] 然后当二维用——那样是连续内存,不是真正的指针数组语义。
- 正确做法分三步:
int** mat = new int*[rows]→ 循环mat[i] = new int[cols]→ 初始化 - 错误写法:
int** mat = new int*[rows]; mat[0] = new int[rows * cols];,这样mat[1]指向的仍是未初始化的垃圾地址 - 性能注意:这种“指针数组+独立行分配”方式局部性差,访问速度不如一维连续数组 + 手动索引
mat[i * cols + j]
void** 不该直接用于存储对象地址
有人想用 void** 当通用二级指针容器,比如统一管理不同类型的指针数组。这很危险。
立即学习“C++免费学习笔记(深入)”;
-
void*可以存任意对象地址,但void**解引用时编译器不知道目标类型大小,**pp会按void*大小(通常是 8 字节)读取——如果实际指向int(4 字节)或double(8 字节),行为未定义 - 安全替代:用模板(如
std::vector<:unique_ptr>></:unique_ptr>)或std::variant<void int double></void>,避免裸void** - 唯一合理场景:系统 API(如
qsort的比较函数参数)明确要求const void**,此时需严格按文档约定使用
new 和 malloc 混用会直接导致 undefined behavior
这是最容易被忽略的坑:分配和释放必须配对。
- 用
new[]分配的int**,必须用delete[]释放;用malloc分配的,必须用free - 尤其注意:C++ 中
new调用构造函数,malloc不调用;混用可能造成对象未析构或内存布局错乱 - 现代 C++ 强烈建议用
std::vector<:string></:string>或std::vector<:vector>></:vector>替代裸多级指针,省去手动内存管理
真正麻烦的从来不是“怎么写分配代码”,而是“哪一级该分配、哪一级只是赋值、哪一级根本不用动”。每次写 **p 前,先在纸上画出三级内存关系图——地址在哪一级、数据在哪一级、谁负责释放——比硬背语法管用得多。


















