关于按值传递和按引用传递(送给这个方面的新手——包括我自己)
我記得剛上大學我們學院就給我們開了第一門專業課——高級語言程序設計。在函數一節里面,首先要學到形式參數和實際參數,然后就學了按值傳遞和按引用傳遞,當時學得那叫一個云里霧里啊,再加上后面還學了個指針,弄得我完全是丈二和尚摸不著頭腦……好在我記住了一段話,并把它做為金科玉律,還是讓我勉強在編程的時候不會搞出太多錯來。
?
這段話就是:凡是在函數定義里面的形式參數為類類型的,函數調用時實際參數為對象,此時為按引用傳遞;凡是在函數定義里面的形式參數為值類型的,函數調用時實際參數為值,此時為按值傳遞。
?
還好,這句話有些繞口但不是特別繞口。
現如今,我編程再也不用C和C++了(我皈依到Microsoft門下),真正做應用的時候,那些問題我也從來不再考慮,可是前幾天同學弄的一個問題著實讓我迷糊了半天。
總之,我先把代碼寫下來吧。在VS中新建一個控制臺應用程序,改寫其Program.cs文件如下:
?
Codeusing?System;
using?System.Collections.Generic;
using?System.Text;
namespace?Test
{
????class?Program
????{
????????static?void?Main(string[]?args)
????????{
????????????int?i?=?0;
????????????string?s?=?"hello";
????????????A?a?=?new?A();
????????????a.i?=?10;
????????????a.s?=?"abcd";?
????????????Console.WriteLine(i);
????????????Console.WriteLine(s);
????????????Console.WriteLine(a);
????????????Console.WriteLine("----------------------------------------------------------");
????????????changeInt(i);
????????????changeString(s);
????????????changeA(a);
????????????Console.WriteLine(i);
????????????Console.WriteLine(s);
????????????Console.WriteLine(a);
????????????Console.Read();
????????}
????????private?static?void?changeInt(int?i)
????????{
????????????i++;
????????}
????????private?static?void?changeString(string?s)
????????{
????????????s?=?"world";
????????}
????????private?static?void?changeA(A?a)
????????{
????????????a.i++;
????????????a.s?=?"hijk";
????????}
????????private?class?A
????????{
????????????public?int?i;
????????????public?string?s;
????????????public?override?string?ToString()
????????????{
????????????????return?"The?int?value?is?"?+?i.ToString()?+?"?and?the?string?value?is?"?+?s;
????????????}
????????}
????}
}
有興趣的話,先想想在控制臺里會打出來什么結果——當然啦,這種小兒科只能糊弄像我這樣的菜鳥。。。。結果我先寫下來
?
Code0
hello
The?int?value?is?10?and?the?string?value?is?abcd
----------------------------------------------------------
0
hello
The?int?value?is?11?and?the?string?value?is?hijk
?
其實我也先為自己辯解幾句,上面這東西迷糊人,Microsoft也有責任,從前在C的年代,哪有string這東西,什么時候我們都用char*,這肯定是個指針。現如今說int是值類型吧,它有個Int32的結構(Java更狠,直接就是Integer的類),說String是個引用吧,它還有個小寫的string的關鍵字。微軟讓高人方便了,卻讓像我這樣的矬人傻了眼。
?
不多說,看上面代碼。明眼人一看,第一個changeInt(int i)的方法就是狗屁,這顯然是按值傳遞,以前那個i紋絲不動;再看第三個changA(A a),這個方法也沒什么,A是我定義的類型,肯定是按引用傳遞,方法里面改了A的公共字段,外面的A也得跟著改;最后看一下changeString(string s),直說了吧,這個也是按引用傳遞,在函數里面改了s,白癡問題來了,函數里面改了s,怎么改完了輸出不跟著變呢?
?
其實這段程序純是騙小孩玩的,不管我傳的是個string還是個String,都是一碼事,全是按引用傳遞的。這段代碼和那個changeA(A a)的區別就在于,changeA改的是a的公共字段,而changeString改的是s本身。如果我在changeA的第一句添上a=new A();再運行這段代碼,就會發現最后一句輸出的a和從前的結果是一樣的。
?
說到底,C#和Java說是不用指針,那不可能,沒指針哪來的NullReferenceException和NullPointerException啊。對于按引用傳遞的對象來說,函數在調用的時候,創建了一個新的指針(Java中的pointer、C#中的reference),指向的是那個對象。這個東西存的就是那個對象在內存里的地址,和C里面的指針是一個東東,只是不讓+、-而已。然后我們在changeString里把這個地址指向了"world"的內存地址,這里改變的只是新創建出來的那個指針,而原來那個指向"hello"的沒跟著變,所以打印語句打出來的還是hello。對于changeA來說,新創建出來的指針指向地址的和Main函數的a指向的是一個地方,由于在changeA里面我們沒給它重新定向,所以我改了changeA里面的a,Main函數里面的a也跟著改了。
?
現在那條金科玉律還是對的了,只不過我要恬不知恥地加上:看吧,如果你用VS來開發程序,對于函數按引用傳遞的參數來說,如果你改的東西是.出來的,那就改變了函數外面那個對象,如果你把形參拿下來直接后面就放=了,那外面就不改啦,嘿嘿嘿^_^
?
PS:看客請不要逼問我指針的定義是啥,如果你認為C#里面reference不是指針我也不反對
轉載于:https://www.cnblogs.com/wodehuajianrui/archive/2008/07/30/1256710.html
總結
以上是生活随笔為你收集整理的关于按值传递和按引用传递(送给这个方面的新手——包括我自己)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: OWC的问题——散点图与折线图如何才能同
- 下一篇: 没了良心