C++中createArray_2/3正确,incorrectCreateArray_1/2错误的原因解析
我无法理解为何createArray_2和createArray_3是正确的数组创建函数,而incorrectCreateArray_1和incorrectCreateArray_2是错误的。我认为incorrectCreateArray_1传递指针并分配数组是可行的,incorrectCreateArray_2返回指向数组的指针也没问题,恳请解答其中原因。
完整代码示例
数组创建函数
// createArray_1 returns the array as a return value double* createArray_1( ) { return new double [ 10 ]; } // createArray_2 returns the array from the parameter list // (using a reference parameter) void createArray_2( double*& arr ) { arr = new double [ 10 ]; } // createArray_3 returns the array from the parameter list // (without using a reference parameter but simulating // pass-by-reference using a pointer) void createArray_3( double** arr ) { *arr = new double [ 10 ]; } // What is wrong with the following two functions? // void incorrectCreateArray_1( double* arr ) { // arr = new double [ 10 ]; //} // double* incorrectCreateArray_2( ) { // double arr[ 10 ]; // return arr; // }
main函数
int main() { double* D; D = createArray_1(); delete [] D; createArray_2( D ); delete [] D; createArray_3( &D ); delete [] D; return 0; }
正确函数的工作原理
createArray_2:指针的引用参数
double*& arr是指针类型的引用,它是main函数中D变量的别名。当函数内执行arr = new double[10]时,本质是直接修改main里的D,让它指向new在堆上分配的数组。后续main里的delete [] D能正确释放这块堆内存。
createArray_3:二级指针参数
double** arr是指向指针的指针,main中传入的&D是指针D自身的地址。函数内的*arr = new double[10],是通过指针的间接访问直接修改main里的D变量,效果和引用参数完全一致,最终D会指向合法的堆数组,释放操作也能正常执行。
错误函数的问题根源
incorrectCreateArray_1:值传递的指针参数
C++中参数默认是值传递,double* arr作为参数时,会创建一个D的副本。函数内arr = new double[10]只是修改了这个副本的指向,对main里的原始D没有任何影响。main中的D依然是未初始化的无效值,后续使用会触发未定义行为;同时new出来的堆内存没有任何指针持有,直接造成内存泄漏。
incorrectCreateArray_2:返回栈数组的指针
函数内的double arr[10]是栈上的局部数组,栈内存会在函数执行完毕后被系统自动回收。返回这个数组的指针,得到的是一个指向已释放内存的野指针。后续对该指针的任何操作(比如访问元素、调用delete)都会导致未定义行为,比如程序崩溃、数据损坏等。
内容的提问来源于stack exchange,提问作者yigitkucuk

