C++中参数传递一般采用的是按值传递,即赋值一个实参的样本然后传入形参,在函数中对形参的改变并不影响实参(如果形参是引用的话那么将会影响到实参),例如
modify(int a){....} 那么int b=2;modify(b),那么这里相当于复制了一份b即temp = b,然后将temp传入函数中,在modify中对a的改变将不会影响到b(仅对temp起作用)。如果将modify改为modify(int&a){。。。}那么在函数中对a的改变将影响到b,因为这里传入的直接是b而不存在temp,即相当于将实参传入了进去。要注意这种复制实参再传入函数的方式。
如果形参是一个指针的话,例如对于函数void test(int* p{...}; int* q = a; test(q);q是一个指针,那么q的内容其实是地址---这里是a的地址假设a的地址是0x3fff那么q的内容就是0x3fff,那么传入test后,其实也是按值传递,这里是复制了q的内容传入进去即temp=q=0x3fff将temp传入函数中,因为temp和q的内容都是一样的即都是a的地址,那么在函数test中改变了a的内容的话将会影响到函数外a的内容--因为是直接对地址进行操作,但无论在test中如何操作p(例如释放a的内存啊等等)都不会改变q的内容,因为传入的是temp而不是q本身,那么q的内容将一直保持不变即其内容都是指向a的地址(q=0x3fff保持不变)。
这样的话,如果我们想在test中让q指向另外一个内存将不可能(因为按值传递,其内容不变即都是a的地址),那么如果我们想在test函数中将q指向的内存释放掉然后为其分配另外一块内存呢?例如如下这样的操作:
void test2(int* p)
{
int* t = p;
p = new int[5];
for(int i=0;i<5;i++)
p[i] =4;
delete t;
}
int main()
{
int*q = new int[3];
for(int i=0;i<3;i++)
q[i] =1;
test2(q);
print(q);
}
这样结果会是什么呢?事实证明结果会是三个奇怪的数:-572662307 -572662307 -572662307 (也有可能是其他三个怪异额数),为什么会这样呢?因为假设在main中q指向的地址为0x1ff,那么传入test2中时将发生这样的事:首先复制q的内容即创造一个副本temp = q =0x1ff,然后将temp传入test2中,那么在test2中的操作将是如下:temp的内容传递给p即p= temp = ox1ff,然后是t = p = 0x1ff,然后p指向了新的地址这里假设是0x1cc(p=ox1cc),然后为p赋值然后释放掉t指向的内存即释放掉ox1ff和接下来的一直遇到0的内存即将int[3]的内存全释放掉了。函数返回时temp,p都将不存在了(临时变量和局部变量)。这样在main中q的值仍然没变仍然是ox1ff但ox1ff这里的内存被test2函数给释放掉了,所以打印出来的将是三个奇怪额数字。
那么如何实现我们想要的效果呢?即在test2函数中真正对q的指向地址进行改变?这里又用到了开头提高的按引用传递,即将test2改为void test2(int*&p)即,那么传入的参数将不会有temp而是直接q本身,那么在里面释放内存和将p指向新的内存都将直接影响到q的指向。
综上:不管按值传递还是传递指针,都会复制一个副本(按值传递副本的内容是值,按指针传递副本的内容是地址),都不会影响到实参的本身内容(按值传递不会影响到实参的值,按指针传递不会影响到指针的值即地址);而若想真正影响到实参的内容只有按引用传递。这里很多教材都将按指针和按引用传递划分为一类,其实是不太合理的,但他们对于按指针传递关注的不是指针本身的内容(地址)而是它指向的内容,故这里需要区分一下。