指针未初始化错误:函数内分配内存为何仍触发报错?
一、为什么会出现"using uninitialized value"错误?
先看你的第一个代码片段:在main函数里你声明了int *a;但没有初始化,然后把它传给citire函数。这里的关键是C++中指针参数默认是按值传递的——也就是说,citire函数里的a是main中a的一个副本。
你在citire里执行a = new int[100];,只是给这个副本指针分配了内存,而main里的原始a依然是一个未初始化的野指针!当你回到main执行cout << *a << " ";时,编译器检测到这个原始指针从未被赋值,自然会抛出"using uninitialized value"的错误。
如果在main里提前给a分配内存,代码能运行是因为此时main的a已经指向了有效内存,虽然citire里的副本指针被重新赋值,但main里的原指针不受影响,依然指向你提前分配的内存,所以访问时不会出问题。
修正方法:使用指针引用传参
要让citire函数修改main里的原始指针,需要把参数改成指针的引用:
#include <iostream> using namespace std; // 把int* a改成int*& a,这样操作的就是main里的原指针 void citire(int& n, int*& a) { cin >> n; a = new int[100]; for (int i = 0; i < n; i++) { cin >> a[i]; } } int main() { int n, *a; citire(n, a); for (int i = 0; i < n; i++) { cout << a[i] << " "; // 这里也要改成a[i],之前的*a只会输出第一个元素哦 } delete[] a; // 别忘了释放内存,避免内存泄漏 return 0; }
二、为什么数组传参不用引用就能修改内容?
这是C++的一个特性:当数组作为函数参数时,会自动退化为指向数组首元素的指针。
看你的第二个代码片段,void citire(int& n, int a[])里的a[]本质上等价于int* a——传递的是数组首元素的地址的副本。虽然是副本,但这个指针指向的是main里int a[100]的内存空间,所以你在citire里通过a[i]访问和修改的是原数组的内存,自然能改变main里数组的内容。
而之前的指针传参问题在于,你修改的是指针变量本身(给它赋值新的内存地址),但因为是值传递,这个修改只作用于副本,原指针根本没变化。如果只是通过指针访问/修改它指向的内容,那不管是指针传值还是数组传参,效果都是一样的——比如如果你在第一个代码里不是重新给a分配内存,而是直接用它指向的内存(前提是已经初始化),那传值也能修改内容。
总结一下:
- 数组传参退化为指针,传递的是数组首地址的副本,操作的是原数组内存
- 指针传值时,修改指针变量本身(比如赋值新地址)不会影响原指针;但通过指针访问指向的内容,会修改原内存
内容的提问来源于stack exchange,提问作者user14399919

