C++ 以指针(*)作为参数和以指针引用(*&)作为参数的区别

首先说结论,传入指针只能更改指针所指向的那一块内存的数据,传入指针引用既能修改指针本身的地址也能修改指针所指向的内存。

假设现在有这样一个功能:传入一个数组指针,并将另一个数组的地址赋值给被传入的指针,以完成数据更新功能。

定义两个函数,分别以指针和指针引用为参数:

//数组大小
const int arraySize = 10;
//备用数组,用于替换传入到函数中的数组指针
int sourceArray[arraySize] = {10,9,8,7,6,5,4,3,2,1};
//辅助函数,用于打印数组中的全部数据
void printArray(int* array,int size)
{
    QString str;
    for(int i = 0; i < size; i++)
    {
        str.append(QString::number(array[i])).append(" ");
    }
    qDebug()<<str;
}
//传入数组指针
void changePtr(int* array)
{
    qDebug()<<"pointer to:"<<array<<"address of pointer is:"<<&array;
    array = sourceArray;
}
//传入数组指针引用
void changePtrRef(int*& array)
{
    qDebug()<<"pointer to:"<<array<<"address of pointer is:"<<&array;
    array = sourceArray;
}

然后在main函数中定义如下代码:

 1 int main()
 2 {
 3     int* targetArray = new int[arraySize];
 4     for(int i = 0; i < arraySize; i++)
 5     {
 6         targetArray[i] = (i+1)*10;
 7     }
 8     qDebug()<<"pointer to:"<<targetArray<<"address of pointer is:"<<&targetArray;
 9     printArray(targetArray,arraySize);
10 
11     changePtr(targetArray);
12     printArray(targetArray,arraySize);
13 
14     changePtrRef(targetArray);
15     printArray(targetArray,arraySize);
16 }

 

在main函数中,定义了一个targetArray数组,并将这个数组初始化为{10,20,30,40,50,60,70,80,90,100},分别将这个数组传入到changePtr函数和changePtrRef中,在这两个函数中会分别打印传入数组指针的地址和指针指向的地址,在更替了数组指针之后,打印数组中的内容。

运行程序,输出如下:

 #8:数组targetArray定义完成之后,自身的地址为0xa9fc40,指针指向的地址为0x34f1bd0,此时数组内的数据为:"10 20 30 40 50 60 70 80 90 100 "

#11:将数组targetArray传入到changePtr(int*)函数中,此时传入的指针自身的地址为0xa9fc00,指针指向的地址为0x34f1bd0,由此可以发现,此时在changePtr函数内的指针虽然也指向地址0xa9fc40,但是它本身却是targetArray指针的一个拷贝。也就是说,存在两个不一样的指针,但是它们都指向同一个地址。

#12:changePtr(int*)执行完成之后,打印targetArray数组中的内容:"10 20 30 40 50 60 70 80 90 100 "可以发现数组中的值其实还是以前的值。changePtr(int*)替换指针并没有真正能做到更新数组的内容,因此被替换的指针实际上是targetArray的一个拷贝,真正的targetArray并没有受到任何影响。

#14:将数组指针传入到changeRefPtr(int*&)函数中,此时传入的指针自身的地址为0xa9fc40,指针指向的地址为0x34f1bd0,这个地址和targetArray完全一致,说明此时changeRefPtr(int*&)函数中所使用的指针就是targetArray本身,而不是targetArray的一个拷贝。

#15:changeRefPtr(int*&)执行完成之后,打印targetArray数组中的内容:"10 9 8 7 6 5 4 3 2 1 ",此时数组中的内容被更新。

结论:当传入指针的时候,函数内部使用的指针是外部指针的一个拷贝,此时只能对指针所指向的内容进行修改,而无法更改指针本身的地址(这种情况还会出现在最后的例子中)。当传入指针的引用时,函数内部使用的就是外部指针本身,此时既可以修改指针所指向的内容,也可以对指针本身进行修改。

补充:传入一个数组空指针,在函数内部对数组分配内存并初始化数组。

 1     void initArray(int* array)
 2     {
 3         array = new int[10];
 4         for(int i = 0; i < 10; i++)
 5         {
 6             array[i] = i;
 7         }
 8     }
 9     
10     int main()
11     {
12          int * target= nullptr;
13          initArray(target);
14     }

#13:这一行代码执行完成之后,target依然是一个空指针,以为内存被分配到另一个地址的指针上了,array本身没有得到任何改变。但是如果initArray(int* array)更改为initArray(int*& array)之后,target就能被正确地初始化。

 

posted @ 2024-02-20 15:24  lccsuse  阅读(14)  评论(0编辑  收藏  举报