假设你现在有一本书A, 放在书柜的第二格里。 A的封面上写着数字1, 而你要做的事情是把A的封面上的数字改为2.
很简单,但是你要通过使用C++的函数来完成这件事情。
是不是瞬间就变难了?
C++的参数传递方式有三种: 值传递,引用传递和指针传递。
你现在要做的事情是把A的封面上的数字改为2, 下面说说通过以上三种方式,你(C++)是怎么去做这件事的。
1 值传递
你把A复制出了一本一模一样的书, 记为B.
B的封面上也写着数字1, 然后你把B传给了函数modify1。
代码描述就是:
void modify1(int book)
{
book = 2;
}
int main()
{
int A = 1; //书A
modify1(A);
return 0;
}
函数modify1把B的封面上的数字改为了2, 然后函数modify1的工作就完成了。
但是却没有达到你想要的效果,因为此时A的封面上的数字还是1. 为什么,因为你拿给函数的书是B, 所以改的也是B, 不会影响到A.
所以值传递就是复制一个实参的值传递给函数。 不管函数做了什么事情,都不会影响实参。
2 引用传递
你现在想着,干脆把A本身直接传给函数modify2算了。
代码描述:
void modify2(int& book) //注意&
{
book = 2;
}
int main()
{
int A = 1; //书A
modify2(A);
return 0;
}
此时你发现A的封面上的数字果然 神奇地 变为了2, 为什么? 因为你拿给函数的书就是A啊 。
你的任务完成了。
所以引用传递就是把实参本身直接传递给函数,函数做什么事,都是直接操作在实参本身。
3 指针传递
但是你发现引用传递竟然要亲自把书A拿给函数modify2, 如此艰苦的活儿让你感到实在是难以胜任…
路人说,让函数自己去拿书不就行了吗,你的格局瞬间就打开了。
于是你写了一张小纸条,内容是: “书A放在书柜的第二格里”。 并把这个小纸条递给了函数modify3.
代码描述:
void modify3(int* note)
{
*note = 2;
}
int main()
{
int A = 1; //书A
int* note = &A; //note就是你写的小纸条
modify3(note);
return 0;
}
于是你 又再次神奇地 发现果然书A的封面上的数字也变成了2。
所以指针传递就是把实参的地址传递给函数,函数做什么事,同样也是直接操作在实参本身。
解释一下,小纸条就是指针,小纸条的内容就是书A的位置(指针的值就是书A的地址)。
你可以这样理解: 函数拿到书A的地址后,函数就会自己去取书A, 所以函数做的事情就是直接操作在书A上。
很好! 你已经精通了C++的三种参数传递机制。
现在,身为参数传递大师的你,经常通过指针传递往书A里写入一些不可告人的秘密…
别问为什么是指针传递,问就是高级。
但是每次函数帮你写完小秘密后,小纸条还留着,并且还保留着书A的位置。
那这样肯定不行啊,绝对不能让别人看到你把书A藏在哪里了。
所以每当函数做完它的事情,你就要把小纸条销毁。
void modify3(int* note)
{
*note = 520;
}
int main()
{
int A = 1;
int* note = &A; //note就是你写的小纸条
modify3(note);
note = NULL; //每当函数做完它的事情, 你就要把小纸条销毁
return 0;
}
嗯,这样就没有人会知道了。
但是身为驰名中外的参数传递大师,如此简单的事情怎么还要你亲自来做。 由于你的格局已经被路人打开过,所以你很快就想到可以让函数来帮你做这件事,既高效又安全。
于是你把那行代码换一下位置就行了,连注释都没改。
void modify3(int* note)
{
*note = 520;
note = NULL; //每当函数做完它的事情, 你就要把小纸条销毁
}
int main()
{
int A = 1;
int* note = &A; //note就是你写的小纸条
modify3(note);
return 0;
}
嗯,不愧是你。
第二天,你身败名裂了。
有人看到了你的小纸条里写的内容,并扒开了你所有的秘密…
明明你已经让函数在写完你的秘密后就把小纸条销毁,为什么小纸条还在?
百思不得其解兼恼羞成怒的你抓起函数直接就是一把乌鸦坐飞机。
然后你发现函数竟然私下藏了一张同样的小纸条!
原来,每次你把你写的小纸条传递给函数时,函数就把你的小纸条的内容抄到它自己的小纸条里,并没有真正使用你的小纸条。 所以函数销毁的也是它自己的小纸条,而不是你的。 因此你的小纸条就被别人看到了。
解释一下,上述的指针传递,本质其实是值传递。 所谓"指针传递",意思其实是函数的形参类型是一个指针。
举个例子:
void func(char c);
这个函数采用的是什么参数传递方式? 当然是值传递,而不是"字符传递"。
void modify3(int* note);
同样地, int* 在这里表明note是一个指针类型,而不是一个"表明参数传递方式的标识符"。
所以说指针传递的本质就是值传递,这就解释为什么函数它会有自己的小纸条,因为是值传递,所以它复制了你的小纸条。
你后悔莫及,你本就应该老老实实地用引用传递而不是为了装X而用指针传递 。
但是你又怎么可能甘心就用朴素的引用传递呢,怎么说你也曾是个大师…
只见你轻轻按下Shift + 7
void modify4(int*& note)
{
*note = 520;
note = NULL; //每当函数做完它的事情, 你就要把小纸条销毁
}
int main()
{
int A = 1;
int* note = &A; //note就是你写的小纸条
modify4(note);
return 0;
}
事了拂衣去,深藏功与名。