java世界
          有些人注定要生活在彼岸,可以親近可以愛憐,甚至可以窮盡一生去思念,只是無(wú)法觸及有些距離,注定不能跨越只能倆倆相望,就像有些愛只能養(yǎng)在心里長(zhǎng)在眼中,不能捧在手里放在身邊,注定只能邂逅無(wú)法遭遇!
          posts - 12,comments - 15,trackbacks - 0

          傳值?還是傳引用?

          (Wang hailong)

           

          關(guān)于編程的參數(shù)傳遞問題,總是存在著這樣的爭(zhēng)論。傳值?還是傳引用?(還是傳指針?還是傳地址?)這些提法,經(jīng)常出現(xiàn)在C++, java, C#的編程技術(shù)文檔里面。這個(gè)問題也經(jīng)常引起開發(fā)人員的爭(zhēng)論,徒耗人力物力。實(shí)際上,這根本不成為問題,只是由于人為加入的概念,混淆了人們的視聽。

          從程序運(yùn)行的角度來(lái)看,參數(shù)傳遞,只有傳值,從不傳遞其它的東西。只不過(guò),值的內(nèi)容有可能是數(shù)據(jù),也有可能是一個(gè)內(nèi)存地址

          開發(fā)人員應(yīng)該了解程序的編譯結(jié)果是怎樣在計(jì)算機(jī)中運(yùn)行的。程序運(yùn)行的時(shí)候,使用的空間可以分為兩個(gè)部分,棧和堆。棧是指運(yùn)行棧,局部變量,參數(shù),都分配在棧上。程序運(yùn)行的時(shí)候,新生成的對(duì)象,都分配在堆里,堆里分配的對(duì)象,棧里的數(shù)據(jù)參數(shù),或局部變量。

          下面舉一個(gè)C++的例子。

          public class Object{

            int i;

            public Object(int i){

                 this.i = i;

            }

           

                 public int getValue(){

                        return i;

                 }

           

                 public void setValue(int i){

                        this.i = i;

                 }

          };

           

          class A {

                 Void func1(int a, Object b){

                        Object * c = new Object( a );

                       

          b = c;

                 }

           

          public      void main(){

                 Object * param = new Object( 1 );

           

                        func1( 2,  param )

                       

                        // what is value of parram now ?

                        // it is still 1.

              }

          };

           

          我們來(lái)看一下,當(dāng)調(diào)用到func1函數(shù)時(shí),運(yùn)行到Object * c = new Object( a ); 棧和堆的狀態(tài)。不同編譯器生成的代碼運(yùn)行的結(jié)果可能會(huì)稍有不同。但參數(shù)和局部變量的大致排放順序都是相同的。

           

          這時(shí)候,我們來(lái)看,param變量被壓入運(yùn)行棧的時(shí)候,只是進(jìn)行了簡(jiǎn)單的復(fù)制。把param里面的內(nèi)容拷貝到b里面。這時(shí)候,b就指向了Object(1)。這里的參數(shù)傳遞,是把param的值傳遞給b

          下面我們來(lái)看,程序執(zhí)行到b = c;時(shí)候的堆棧狀態(tài)。

           

          我們可以看到,b現(xiàn)在指向了Object(2)。但是對(duì)param的值毫無(wú)影響。param的值還是Object(1)

          所以,我們說(shuō),對(duì)參數(shù)的賦值不會(huì)影響到外層函數(shù)的數(shù)據(jù),但是,調(diào)用參數(shù)的操作方法,卻等于直接操作外層函數(shù)的數(shù)據(jù)。比如,如果我們?cè)?/SPAN>func1()函數(shù)中,不調(diào)用b=c;而調(diào)用b.setValue(3),那么Object(1)的數(shù)據(jù)就會(huì)變?yōu)?/SPAN>3param的數(shù)據(jù)也會(huì)改變?yōu)?/SPAN>3

          javaC#中的情況,也都是一樣。

          C++還有一種變量定義方法,表面上看起來(lái),不符合上面的說(shuō)明,這里進(jìn)行說(shuō)明。

          Object * a = new Object(1);

          Object & * b = a;

          這里的b就等于是a的另外一個(gè)別名,b就是a。對(duì)b賦值就等于對(duì)a賦值。甚至作為參數(shù)傳遞時(shí),也是如此。對(duì)這種類型的參數(shù)的賦值,就等于對(duì)外層函數(shù)數(shù)據(jù)的賦值。

          public class B{

          void func1(Object & * b){

                 b = new Object(4);

          }

           

          public void main(){

                 Object * a = new Object(1);

           

                 func1(a);

           

                 // a is changed to Object(4) now.

          }

           

          }

          當(dāng)運(yùn)行完func1(a);時(shí),a的值變化為Object(4)。這是因?yàn)榫幾g器實(shí)際把參數(shù)Object & * b編譯為Object ** b_addrb_addr的值是b的地址,也就是a的地址。

          當(dāng)調(diào)用func1()的時(shí)候,實(shí)際上是把b_addr作為參數(shù)壓到棧里,b_addr的值是a的地址。

          當(dāng)執(zhí)行b = new Object(4); 時(shí),實(shí)際執(zhí)行了 b_addr->b = new Object(4); 也就是執(zhí)行了 b_addr->a = new Object(4); a的值當(dāng)然變化了。

           

          還有一點(diǎn)需要說(shuō)明,當(dāng)使用COMCORBA等中間件規(guī)范進(jìn)行開發(fā)時(shí),我們需要定義IDL語(yǔ)言。參數(shù)的類型分為,[in][out][in, out],其中的RPC遠(yuǎn)程調(diào)用的參數(shù)打包規(guī)范,就更復(fù)雜了,但原理卻是一樣的。

          posted on 2005-11-17 09:43 安德爾斯 閱讀(391) 評(píng)論(0)  編輯  收藏

          只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


          網(wǎng)站導(dǎo)航:
           
          主站蜘蛛池模板: 永平县| 濮阳县| 化州市| 白朗县| 兰溪市| 瑞昌市| 定远县| 临澧县| 喜德县| 黄龙县| 吴忠市| 宜昌市| 寻乌县| 抚州市| 张家口市| 南阳市| 大港区| 平安县| 绩溪县| 玉龙| 信丰县| 正宁县| 克山县| 泾阳县| 昆山市| 会东县| 尼木县| 通化县| 石台县| 新化县| 钟山县| 得荣县| 思茅市| 安岳县| 错那县| 特克斯县| 科尔| 象州县| 邹城市| 白城市| 苗栗市|