<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12
      歡迎大家下載試用折桂單點登錄系統, https://www.zheguisoft.com

      c++/java/c# 幾種編程語言的指針、引用比較

      前一段時間,我在 cnblogs 別人的博客中,談到:

      java 中的引用/指針,與 c++/C# 中的引用/指針不是一個概念.

      Java 引用,相當于 c++ 指針(fun3)。Java 引用可以賦值 null, 而 c++ 引用 (見 fun2) 不能賦值 null,c++ 指針可以賦值 null(fun3).
      Java 中,無 c++ 引用(fun2)對應的語法。

       

      結果引起不必要的質疑,特此,寫博客,對c++/java/c# 幾種編程語言的指針、引用,進行比較,期望引起更多的人,對此有所關注。

      從語法上看,三種開發語言中,C++ 的指針、引用,最為復雜,因此,下面的舉例,都從 C++ 代碼開始,然后與 java/c# 的語法進行比較。

       

      1)  C++ 簡單類型變量,有直接變量定義、指針定義、引用定義。

          int aa = 10;//c++
          int &bb = aa;//c++
          int *cc = &aa;//c++

      上述三行代碼,最后三個變量指向同一個數據。相比較而言,java/c# 都只有變量定義,無引用定義、指針定義。補充:感謝 xiaotie 、飛浪 的提醒:C#中是有指針的,在unsafe狀態下,可以定義和使用指針。特更正。

       

      2) C++ 函數調用參數,簡單類型變量,有直接變量定義、指針定義、引用定義,后兩個,在函數內部改變數據,退出函數,能看到改變后的數據。

      void simple_by_val(int a, const int b)
      {
          a=15;
          //b=13;            //error C2166: l-value specifies const object
      
          //a=NULL;        //good
          //b=NULL;        //error C2166: l-value specifies const object
      }
      
      void simple_by_ref(int &a, const int &b)
      {
          a=25;
          //b=23;            //error C2166: l-value specifies const object
      
          //a=NULL;            //good
          //b=NULL;        //error C2166: l-value specifies const object
      
      }
      
      void simple_by_pointer(int *a, const int *b)
      {
          *a = 35;
          //*b = 33;        //error C2166: l-value specifies const object
      
          a = NULL;        //ok
          b = NULL;        //ok
      }

      java 沒有這么多名堂,只有直接變量定義。C# 略為復雜一點,有引用,有 out 參數。

              static void M(int a, ref int b, out int c)
              {
                  c = 13;
              }

      相比較而言,C# 的函數參數( ref int b), 類似于C++的函數參數( int &a),都是調用函數前要賦初值,在函數內部改變數據,退出函數,能看到改變后的數據。

      而 C# 的 (out int c),在 C++/Java 中,無對應的語法。這個可以調用函數前,不賦初值。在 C# 之前,也很少見到這種語法,只在一些數據庫的存儲過程、函數定義中,見過類似語法。估計是從數據庫編程語法中抄襲過來的語法。

      特別注明:C# 的引用( ref int b),只是用在函數參數變量定義上,不能用在函數內部的局部變量中。C++ 中的引用( int &a),可以用在函數內部的局部變量中。

       

      3)  C++ 的類對象變量定義語法,較為復雜,可以定義在stack 上(不用 new),可以定義在 heap(用 new)。

          CMyClass obj;                        //stack
          CMyClass *p2 = new CMyClass();        //heap

      java/C# 中,沒有這么復雜,可以認為是上述兩種“綜合+簡化”了。

       

      4) 在 java/C# 中,如下用法是錯誤的,會報空指針異常;但是在 C++ 里是合法的。

          CMyClass obj;
          obj.run();

      在 C++ 中,

      CMyClass obj;

      以上一行代碼已經調用了構造函數,完成了變量初始化。而在 java/C# 中,這一行代碼相當于:

      CMyClass obj = null;

       

      5) C++ 中,stack 變量出了作用范圍,內存自動回收;heap 變量,需要手工 delete。

      java/C# 中,變量是空閑時自動回收的(理論上的),不是變量出了作用范圍,就內存回收。

       

      {
          CMyClass obj;                        //stack
          obj.test();
      }//此處, stack 變量自動被 delete ,內存自動回收
      
      {
          CMyClass *p2 = new CMyClass();        //heap
          p2->test();
      } //此處,超出變量 p2 的作用范圍,下面不能再用 p2 變量了,但是,內存并未釋放,有內存泄露。

       

       

       

       

      6) 以下代碼在 C++ 中是正確的,在 java/C# 是錯誤的。在 java/C# 語法中,沒有定義變量加 * 的,也不能用 -> 來調用類的函數或類的成員變量,也不能用 delete。

       

      CMyClass *p1 = null;
      CMyClass *p2 = new CMyClass();
      p2->ab();
      delete p2;
      p2 = null;

       

       

      7) 以下代碼,在java/C# 語法中,是正確的,在 C++ 是錯誤的。C++ 中,這種賦值要用指針 (CMyClass *p1 = null;)。

      CMyClass p1 = null;
      CMyClass p2 = new CMyClass();

       

      8) 以下代碼,在 C++ 代碼中,會調用“拷貝構造函數”、"等于號重載函數"。這兩個函數,在 C++ 中,默認會由編譯器自動生成。

          //C++
          CMyClass obj; //調用構造函數 CMyClass obj2 = obj; //調用拷貝構造函數 obj2 = obj; //調用 = 操作符重載函數

      以上代碼,大致相當于 java/C# 中的 克隆"clone"。但更隱蔽(初學者不知道調用了 C++ 構造函數、拷貝構造函數、= 操作符重載函數)、更復雜。java/C# 無操作符重載函數。

      //C#
                  CMyClass obj = new CMyClass();
                  CMyClass obj2 = (CMyClass)obj.Clone();

      而在 C# 中,Clone 函數并不會自動生成。在 Java 中,可以調用 super.clone() ---- Java 基類 Object 默認有一個 clone 函數。

      在 C++ 中,默認會由編譯器自動生成“拷貝構造函數”、"等于號重載函數",這一點,很多時候會造成問題,要特別注意。

      在 C++ 中,函數返回值不要用 CMyClass ,這會造成不必要地調用“拷貝構造函數”、"等于號重載函數";也不要返回引用 CMyClass&, 對函數內局部變量的引用,退出函數后無法繼續使用。而要返回指針 CMyClass *(最好用智能指針包裝后的指針變量)。這一點很多初學者不明白。

      但是 C++ 的 std:string 除外。std:string 的“拷貝構造函數”、"等于號重載函數"經過優化,拷貝后的變量,與拷貝之前的變量,內部使用相同的 char[] 數組,只有當一個 string 變量改變時,才會把 char[] 數組復制成兩份。std:string 的“拷貝構造函數” 沒有性能上損失,又比 string 指針減少了內存泄露,因此,對 std:string ,使用時盡量用 對象變量、對象引用、對象拷貝構造,避免使用 std:string 指針。

      另,java/C# 的 String 變量不可改變(有其它類,比如 java StringBuilder類是可變的),C++ 的 string 變量可以改變。這個細微差異,很多人不明白。

       

      9) C++ 引用語法,有一些是 Java/C# 程序員不知道的語法:

      //C++
      CMyClass &a1; //錯誤,C++ 引用變量定義的時候就要初始化;//Java/C# 對象變量,沒有要求變量定義的時候,就要初始化
      
      CMyClass &a1 = NULL; //錯誤,C++ 引用變量不能賦值 null
      
      CMyClass &a1 = new CMyClass(); //錯誤,C++ 引用變量不能賦值給一個 new 對象,這種情況,要用 C++ 指針。
      
      //以下C++ 代碼是正確的:
      CMyClass a;
      CMyClass &a1 = a;
      
      CMyClass *b =new CMyClass();
      CMyClass &b1 = *b; //這種寫法不常用。

       

       

      10) Sun 自稱 java 中消滅了 C++ 中萬惡的指針,自己的對象變量,都是引用。做個比較:

      C++ 引用不能賦值 null, 不能賦值 new XXX();C++ 指針可以賦值 null, 可以賦值 new XXX()。

      C++ 引用對象通常在 stack 中,而C++ 指針 new 出來的對象則在 heap 中。

       

      java/C# 中的對象變量,可以賦值 null, 可以賦值 new XXX()。java/C# 中的對象變量在 heap 中。

       

      因此,java/C# 中的對象變量,更像是 C++ 中的指針,而不是 C++ 中的引用。

       

      11) C++ 中,指針變量是一個 long 型整數,可以亂指的:

      CMyClass *obj = (CMyClass *) 99;        //compile/run good, should not use    

      如果我知道一個內存地址,就可以定義一個C++指針變量,指向這個內存地址。C++ 的“引用”沒有這個功能。C#/Java 的對象變量更沒有這個功能。

      “指針亂指” 是 C++ 指針功能強大、靈活的體現(PC 上最早出現播放視頻的時候,大概是 intel 486 CPU 時代,C++軟件通常都直接寫顯存,據說這樣速度更快),也是最容易出問題的地方。估計是因為這個原因,所以C#/Java 都去掉了這個功能。所謂“萬惡的C++指針”,多半,也是指的是“指針亂指”。

       

      12) C++ 有野指針,即已經刪除對象,但指針還是指向刪除對象,還可以繼續操作,但運行結果不保證正確。

      CMyClass *p = new CMyClass();
      ...//給 p 指向的內存賦值
      delete p;
      
      //這時 p 仍然指向之前的內存地址,該內存地址數據,一般情況下、短時間內,并沒有被清空或者覆蓋,仍然可以讀/寫。這就是“野指針”。
      p->run(); //運行結果可能正確,可能不正確,沒有保證。
      
      //此時指針 p 對應的內存,可能被下一個 new XXX() 代碼,用了這個內存,因此,理論上講,delete 之后的指針,不應再用來操作對象。
      
      p= NULL; //將指針指向“空”,可以避免“野指針”問題。
      
      p->run(); //這里會報運行時錯誤。也就是空指針異常。空指針異常在 java/c# 中都有。

      C++ 中,delete 與將變量賦值 null , 理應放在一起,可以認為是一個“數據庫事務”一樣的,要么都成功、要么都失敗。其實,delete 關鍵字,是由 C++ 標準定義的,標準中,完全可以要求: delete 所在行的代碼,執行之后,把指針變量變成 null(C++ 標準的規范,很多都是規定編譯器做什么,因此可以加這個規定)。這樣可以避免野指針問題??上?,C++ 標準,在這方面沒有考慮周全。

       

      另,有人抱怨,面試做題,看不是是 C++ 還是 Java、C# , 期望通過看本文,可以幫助一二。

      ---------------------------------------

      歡迎大家下載試用折桂單點登錄系統, http://zheguisoft.com

      posted @ 2012-06-08 17:57  杰克倫敦塵  Views(4705)  Comments(31)    收藏  舉報
      歡迎大家下載試用折桂單點登錄系統, https://www.zheguisoft.com
      主站蜘蛛池模板: 国产一区精品在线免费看 | 五月丁香六月狠狠爱综合| 最新亚洲人成无码WWW| 天天做天天躁天天躁| 激情综合网激情五月激情| 国产一精品一av一免费| 欧美人与禽2o2o性论交| 麻豆亚洲自偷拍精品日韩另| 亚洲中文字幕无码专区| 视频区 国产 图片区 小说区| 国产大片黄在线观看| 国产精品久久久国产盗摄| 日本一区二区三区视频版| 亚洲国产欧美不卡在线观看| 麻豆一区二区中文字幕| 日韩精品亚洲精品第一页| 亚洲一区二区av观看| 亚洲男人AV天堂午夜在| 少妇上班人妻精品偷人| 成人永久性免费在线视频| 天天做天天爱夜夜爽| 日韩精品亚洲专区在线观看| 午夜DY888国产精品影院| 一本一道av无码中文字幕麻豆| 国产毛片精品av一区二区| 国产va在线观看免费| 亚洲av成人无码精品电影在线| 亚洲人成网站色www| 亚洲一区二区三区在线播放无码 | 开化县| 国产欧美精品一区aⅴ影院| 中国亚州女人69内射少妇| 成人国产精品三上悠亚久久| 人妻饥渴偷公乱中文字幕| 任我爽精品视频在线播放| 日韩精品中文字幕人妻| 亚洲理论在线A中文字幕| 国产成人亚洲欧美二区综合| 美女爽到高潮嗷嗷嗷叫免费网站| 91老熟女老女人国产老| 久久久久国精品产熟女久色|