• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            Impossible is nothing  
              愛過知情重醉過知酒濃   花開花謝終是空   緣份不停留像春風(fēng)來又走   女人如花花似夢
            公告
            日歷
            <2025年5月>
            27282930123
            45678910
            11121314151617
            18192021222324
            25262728293031
            1234567
            統(tǒng)計
            • 隨筆 - 8
            • 文章 - 91
            • 評論 - 16
            • 引用 - 0

            導(dǎo)航

            常用鏈接

            留言簿(4)

            隨筆分類(4)

            隨筆檔案(8)

            文章分類(77)

            文章檔案(91)

            相冊

            搜索

            •  

            最新評論

            閱讀排行榜

            評論排行榜

             

            何為指針?

              指針基本上和其它的變量一樣,唯一的一點不同就是指針并不包含實際的數(shù)據(jù),而是包含了一個指向內(nèi)存位置的地址,你可以在這個地址找到某些信息。這是一個很重要的概念,并且許多程序或者思想都是將指針作為它們的設(shè)計基礎(chǔ),例如鏈表。

            開始

              如何定義一個指針?呃,就像定義其它的變量一樣,不過你還需要在變量名之前添加一個星號。例如,下面的代碼創(chuàng)建了兩個指向整數(shù)的指針:
            int* pNumberOne;
            int* pNumberTwo;
              注意到變量名的前綴“p”了嗎?這是編寫代碼的一個習(xí)慣,用來表示這個變量是一個指針。
              現(xiàn)在,讓我們把這些指針指向一些實際的值吧:
            pNumberOne = &some_number;
            pNumberTwo = &some_other_number;
               “&”標志應(yīng)該讀作“the address of(……的地址)”,它的作用是返回一個變量的內(nèi)存地址,而不是這個變量本身。那么在這個例子中,pNumberOne就是some_number的地 址,亦稱作pNumberOne指向some_number。
              現(xiàn)在,如果我們想使用some_number的地址的話,那么我們就可以使用 pNumberOne了。如果我們希望經(jīng)由pNumberOne而使用some_number的值的話,我們可以用*pNumberOne。“*”應(yīng)該讀 作“the memory location pointed to by(由……指向的內(nèi)存位置)”,它用來取得指針所指向的值。不過指針聲明的情況例外,如“int *pNumber”。

            到現(xiàn)在都學(xué)到什么了(一個例子):

              咻!要理解的東西太多了,所以在此我建議,如果你還是不理解以上的概念的話,那么最好再通讀一遍;指針是一個復(fù)雜的主題,要掌握它是要花些時間的。
              這里有一個示例,解說了上面討論的那些概念。它是由C編寫成,并不帶有C++的那些擴展。
            #include <stdio.h>
            void main()
            {
              // 聲明變量:
              int nNumber;
              int *pPointer;
              // 現(xiàn)在,給它們賦值:
              nNumber = 15;
              pPointer = &nNumber;
              // 打印nNumber的值:
              printf("nNumber is equal to : %d\n", nNumber);
              // 現(xiàn)在,通過pPointer來控制nNumber:
              *pPointer = 25;
              // 證明經(jīng)過上面的代碼之后,nNumber的值已經(jīng)改變了:
              printf("nNumber is equal to : %d\n", nNumber);
            }
              請通讀并編譯以上代碼,并確信你已經(jīng)弄懂了它是如何工作的。然后,當(dāng)你準備好了以后,就往下讀吧!

            陷阱!

              看看你是否能指出以下程序的缺陷:
            #include <stdio.h>
            int *pPointer;
            void SomeFunction()
            {
              int nNumber;
              nNumber = 25;   
              // 使pPointer指向nNumber:
              pPointer = &nNumber;
            }
            void main()
            {
              SomeFunction(); // 讓pPointer指向某些東西
              // 為什么這樣會失敗?
              printf("Value of *pPointer: %d\n", *pPointer);
            }
               這個程序首先調(diào)用SomeFunction函數(shù),在其中創(chuàng)建了一個名為nNumber的變量,并且使pPointer指向這個變量。那么,這就是問題之 所在了。當(dāng)函數(shù)結(jié)束的時候,由于nNumber是一個本地變量,那么它就會被銷毀。這是因為當(dāng)語句塊結(jié)束的時候,塊中定義的本地變量都會被銷毀。這就意味 著當(dāng)SomeFunction返回到main()的時候,那個變量就已經(jīng)被銷毀了,所以pPointer將會指向一個不再屬于本程序的內(nèi)存位置。如果你不 懂這一點,那么你應(yīng)該去讀一讀有關(guān)本地變量、全局變量以及作用域的東西,這些概念非常重要。
              那么,如何解決這個問題呢?答案是使用一種名為動態(tài)分配的技術(shù)。請注意:在這一點上,C和C++是不同的。既然大多數(shù)開發(fā)者正在使用C++,那么下面的代碼就使用C++來編寫。

            動態(tài)分配

              動態(tài)分配也許可以算是指針的關(guān)鍵技術(shù)了。它被用于在沒有定義變量的情況下分配內(nèi)存,然后由一個指針指向這段內(nèi)存。雖然這個概念好像很讓人糊涂,其實它很簡單。以下的代碼解說了如何為一個整數(shù)分配內(nèi)存空間:
            int *pNumber;
            pNumber = new int;
              第一行代碼聲明了一個指針pNumber,第二行代碼分配了一個整數(shù)的空間,并使pNumber指向這一段新分配的內(nèi)存。下面是另外一個例子,這一次使用了一個double:
            double *pDouble;
            pDouble = new double;
              這些規(guī)則是相同的T,所以你應(yīng)該可以很容易地掌握。
              動態(tài)分配和本地變量的不同點是:你分配的內(nèi)存在函數(shù)返回和語句塊結(jié)束的時候不會被釋放,所以,如果你用動態(tài)分配來重新編寫上面的代碼,那么它就會正常工作了:
            #include <stdio.h>
            int *pPointer;
            void SomeFunction()
            {
              // 使pPointer指向一個new的整數(shù)
              pPointer = new int;
              *pPointer = 25;
            }
            void main()
            {
              SomeFunction(); // 讓pPointer指向某些東西
              printf("Value of *pPointer: %d\n", *pPointer);
            }
               請通讀并編譯以上的示例代碼,并確信你已經(jīng)弄懂了它為何如此工作。當(dāng)調(diào)用SomeFunction的時候,它分配了一段內(nèi)存,并使pPointer指向 這段內(nèi)存。這一次當(dāng)函數(shù)返回的時候,這段new的內(nèi)存就會完好保留,所以pPointer仍然指向某些有用的內(nèi)容。這就是動態(tài)分配了!請確信你已經(jīng)搞懂了 這一點,然后繼續(xù)閱讀關(guān)于這段代碼中的一個嚴重錯誤。

            來得明白,去得明白

              還有一個復(fù)雜的因素,并且是十分嚴重的——雖然它很好補救。問題是你分配的內(nèi)存在離開的時候雖然仍然完好,但是這段內(nèi)存永遠也不會自動銷毀。這 就是說,如果你不通知電腦結(jié)束使用的話,這段內(nèi)存就會一直存在下去,這樣做的結(jié)果就是內(nèi)存的浪費。最終,系統(tǒng)就會因為內(nèi)存耗盡而崩潰。所以,這是相當(dāng)重要 的一個問題。當(dāng)你使用完內(nèi)存之后,釋放它的代碼非常簡單:
            delete pPointer;
              這一切就這么簡單。不管怎樣,在你傳遞一個有效的指針——亦即一個指向一段你已經(jīng)分配好的內(nèi)存指針,而不是那些老舊的垃圾內(nèi)存——的時候,你都需要無比細心。嘗試delete一段已經(jīng)釋放的內(nèi)存是十分危險的,這可能會導(dǎo)致你的程序崩潰。
              好了,下面又是那個例子,這一次它就不會浪費內(nèi)存了:
            #include <stdio.h>
            int *pPointer;
            void SomeFunction()
            {
              // 使pPointer指向一個new的整數(shù)
              pPointer = new int;
              *pPointer = 25;
            }
            void main()
            {
              SomeFunction(); // 讓pPointer指向某些東西
              printf("Value of *pPointer: %d\n", *pPointer);
              delete pPointer;
            }

              唯一的一行不同也就是最本質(zhì)的一點。如果你不將內(nèi)存delete掉,你的程序就會得到一個“內(nèi)存泄漏”。如果出現(xiàn)了內(nèi)存泄漏,那么除非你關(guān)閉應(yīng)用程序,否則你將無法重新使用這段泄漏的內(nèi)存。

            向函數(shù)傳遞指針

              向函數(shù)傳遞指針的技術(shù)非常有用,但是它很容易掌握(譯注:這里存在必然的轉(zhuǎn)折關(guān)系嗎?呃,我看不出來,但是既然作者這么寫了,我又無法找出一個合適的關(guān)聯(lián)詞,只好按字面翻譯了)。如果我們要編寫一段程序,在其中要把一個數(shù)增加5,我們可能會像這么寫:
            #include <stdio.h>
            void AddFive(int Number)
            {
              Number = Number + 5;
            }
            void main()
            {
              int nMyNumber = 18;
              printf("My original number is %d\n", nMyNumber);
              AddFive(nMyNumber);
              printf("My new number is %d\n", nMyNumber);
            }

               可是,這段程序AddFive中的Number是傳遞到這個函數(shù)中的nMyNumber的一份拷貝,而不是nMyNumber本身。因此, “Number = Number + 5”這一行則是向這份拷貝加上了5,而main()中的原始變量并沒有任何變化。你可以運行這個程序試著證明這一點。
              對于這個程序,我們可以 向函數(shù)傳遞這個數(shù)字內(nèi)存地址的指針。這樣,我們就需要修改這個函數(shù),使之能接收一個指向整數(shù)的指針。于是,我們可以添加一個星號,即把“void AddFive(int Number)”改為“void AddFive(int* Number)”。下面是這個修改過了的程序,注意到我們已經(jīng)將nMyNumber的地址(而不是它本身)傳遞過去了嗎?此處改動是添加了一個 “&”符號,它讀作(你應(yīng)該回憶起來了)“the address of(……的地址)”。
            #include <stdio.h>
            void AddFive(int* Number)
            {
              *Number = *Number + 5;
            }
            void main()
            {
              int nMyNumber = 18;
              printf("My original number is %d\n", nMyNumber);
              AddFive(&nMyNumber);
              printf("My new number is %d\n", nMyNumber);
            }

              你可以試著自己編寫一個程序來證明這一點。注意到AddFive函數(shù)中Number之前的“*”的重要性了嗎?這就是告知編譯器我們要在指針Number指向的數(shù)字上加5,而不是向指針本身加5。
              最后要注意的一點是,你亦可以在函數(shù)中返回指針,像下面這個樣子:
            int * MyFunction();
              在這個例子中,MyFunction返回了一個指向整數(shù)的指針。

            指向類的指針

              關(guān)于指針,我還有還有兩點需要提醒你。其中之一是指向結(jié)構(gòu)或類的指針。你可以像這樣定義一個類:
            class MyClass
            {
            public:
              int m_Number;
              char m_Character;
            };

              然后,你可以定義一個MyClass的變量:
            MyClass thing;
              你應(yīng)該已經(jīng)知道這些了,如果還沒有的話,你需要閱讀一下這方面的資料。你可以這樣定義一個指向MyClass的指針:
            MyClass *thing;
              就像你期望的一樣。然后,你可以為這個指針分配一些內(nèi)存:
            thing = new MyClass;
               這就是問題之所在了——你將如何使用這個指針?呃,通常你會這么寫:“thing.m_Number”,但是對于這個例子不行,因為thing并非一個 MyClass,而是一個指向MyClass的指針,所以它本身并不包含一個名為“m_Number”的變量;它指向的結(jié)構(gòu)才包含這個m_Number。 因此,我們必須使用一種不同的轉(zhuǎn)換方式。這就是將“.”(點)替換為一個“->”(橫線和一個大于號)。請看下面這個例子:
            class MyClass
            {
            public:
              int m_Number;
              char m_Character;
            };
            void main()
            {
              MyClass *pPointer;
              pPointer = new MyClass;
              pPointer->m_Number = 10;
              pPointer->m_Character = 's';
              delete pPointer;
            }

            指向數(shù)組的指針

              你也可以使指針指向數(shù)組,如下:
            int *pArray;
            pArray = new int[6];

              這將創(chuàng)建一個指針pArray,它會指向一個6個元素的數(shù)組。另一種不使用動態(tài)分配的方法如下:
            int *pArray;
            int MyArray[6];
            pArray = &MyArray[0];

               請注意,你可以只寫MyArray來代替&MyArray[0]。當(dāng)然,這種方法只適用于數(shù)組,是C/C++語言的實現(xiàn)使然(譯注:你也可以把 函數(shù)名賦值給一個相應(yīng)的函數(shù)指針)。通常出現(xiàn)的錯誤是寫成了“pArray = &MyArray;”,這是不正確的。如果你這么寫了,你會獲得一個指向數(shù)組指針的指針(可能有些繞嘴吧?),這當(dāng)然不是你想要的。

            使用指向數(shù)組的指針

              如果你有一個指向數(shù)組的指針,你將如何使用它?呃,假如說,你有一個指向整數(shù)數(shù)組的指針吧。這個指針最初將會指向數(shù)組的第一個值,看下面這個例子:
            #include <stdio.h>
            void main()
            {
              int Array[3];
              Array[0] = 10;
              Array[1] = 20;
              Array[2] = 30;
              int *pArray;
              pArray = &Array[0];
              printf("pArray points to the value %d\n", *pArray);
            }

               要想使指針移到數(shù)組的下一個值,我們可以使用pArray++。我們也可以——當(dāng)然你們有些人可能也猜到了——使用pArray + 2,這將使這個數(shù)組指針移動兩個元素。要注意的一點是,你必須清楚數(shù)組的上界是多少(在本例中是3),因為在你使用指針的時候,編譯器不能檢查出來你是否 已經(jīng)移出了數(shù)組的末尾。所以,你可能很容易地使系統(tǒng)崩潰。下面仍然是這個例子,顯示了我們所設(shè)置的三個值:
            #include <stdio.h>
            void main()
            {
              int Array[3];
              Array[0] = 10;
              Array[1] = 20;
              Array[2] = 30;
              int *pArray;
              pArray = &Array[0];
              printf("pArray points to the value %d\n", *pArray);
              pArray++;
              printf("pArray points to the value %d\n", *pArray);
              pArray++;
              printf("pArray points to the value %d\n", *pArray);
            }

              同樣,你也可以減去值,所以pArray - 2就是pArray當(dāng)前位置的前兩個元素。不過,請確定你是在操作指針,而不是操作它指向的值。這種使用指針的操作在循環(huán)的時候非常有用,例如for或while循環(huán)。
              請注意,如果你有了一個指針(例如int* pNumberSet),你也可以把它看作一個數(shù)組。比如pNumberSet[0]相當(dāng)于*pNumberSet,pNumberSet[1]相當(dāng)于*(pNumberSet + 1)。
              關(guān)于數(shù)組,我還有最后一句警告。如果你用new為一個數(shù)組分配空間的話,就像下面這個樣子:
            int *pArray;
            pArray = new int[6];

              那么必須這樣釋放它:
            delete[] pArray;
              請注意delete之后的[]。這告知編譯器它正在刪除一個整個的數(shù)組,而不是單獨的一個項目。你必須在使用數(shù)組的時候使用這種方法,否則可能會獲得一個內(nèi)存泄漏。

            最后的話

              最后要注意的是:你不能delete掉那些沒有用new分配的內(nèi)存,像下面這個樣子:
            void main()
            {
              int number;
              int *pNumber = number;
              delete pNumber; // 錯誤:*pNumber不是用new分配的
            }

            常見問題及FAQ

              Q:為什么在使用new和delete的時候會得到“symbol undefined”錯誤?
              A:這很可能是由于你的源文件被編譯器解釋成了一個C文件,因為new和delete操作符是C++的新特性。通常的改正方法是使用.cpp作為你的源文件擴展名。

              Q:new和malloc的區(qū)別是什么?
              A:new是C++特有的關(guān)鍵詞,并且是標準的分配內(nèi)存方法(除了Windows程序的內(nèi) 存分配方法之外)。你絕不能在一個C C++程序中使用malloc,除非絕對必要。由于malloc并不是為C++面向?qū)ο蟮奶厣O(shè)計的,所以使用它為類對象分配內(nèi)存就不會調(diào)用類的構(gòu)造函 數(shù),這樣就會出現(xiàn)問題。由于這些原因,本文并不對它們進行討論,并且只要有可能,我亦會避免使用它們。

              Q:我能一并使用free和delete嗎?
              A:你應(yīng)該使用和分配內(nèi)存相配套的方法來釋放內(nèi)存。例如,使用free來釋放由malloc分配的內(nèi)存,用delete來釋放由new分配的內(nèi)存。

            引用

              從某種角度上來說,引用已經(jīng)超過了本文的范圍。但是,既然很多讀者問過我這方面的問題,那么我在此對其進行一個簡要的討論。引用和指針十分相 似,在很多情況下用哪一個都可以。如果你能夠回憶起來上文的內(nèi)容——我提到的“&”讀作“the address of(……的地址)”,在聲明的時候例外。在聲明的這種情況下,它應(yīng)該讀作“a reference to(……的引用)”,如下:
            int& Number = myOtherNumber;
            Number = 25;

              引用就像是myOtherNumber的指針一樣,只不過它是自動解析地址的,所以它的行為就像是指針指向的實際值一樣。與其等價的指針代碼如下:
            int* pNumber = &myOtherNumber;
            *pNumber = 25;

              指針和引用的另一個不同就是你不能更換引用的內(nèi)容,也就是說你在聲明之后就不能更換引用指向的內(nèi)容了。例如,下面的代碼會輸出20:
            int myFirstNumber = 25;
            int mySecondNumber = 20;
            int &myReference = myFirstNumber;
            myReference = mySecondNumber;
            printf("%d", myFristNumber);

              當(dāng)在類中的時候,引用的值必須由構(gòu)造函數(shù)設(shè)置,像下面這種方法一樣:
            CMyClass::CMyClass(int &variable) : m_MyReferenceInCMyClass(variable)
            {
              // 這里是構(gòu)造代碼
            }

            總結(jié)

              這一主題最初是十分難以掌握的,所以你最好讀上它個至少兩遍——因為大多數(shù)人不能立即弄懂。下面我再為你列出本文的重點:

              1、指針是一種指向內(nèi)存中某個位置的變量,你可以通過在變量名前添加星號(*)來定義一個指針(也就是int *number)。
              2、你可以通過在變量名前添加“&”來獲得它的內(nèi)存地址(也就是pNumber = &my_number)。
              3、除了在聲明中以外(例如int *number),星號應(yīng)該讀作“the memory location pointed to by(由……指向的內(nèi)存位置)”。
              4、除了在聲明中以外(例如int &number),“&”應(yīng)該讀作“the address of(……的地址)”。
              5、你可以使用“new”關(guān)鍵字來分配內(nèi)存。
              6、指針必須和它所指向的變量類型相配套,所以int *number不應(yīng)該指向一個MyClass。
              7、你可以向函數(shù)傳遞指針。
              8、你必須使用“delete”關(guān)鍵字來釋放你分配的內(nèi)存。
              9、你可以使用&array[0]來獲得一個數(shù)組的指針。
              10、你必須使用delete[]來釋放動態(tài)分配的數(shù)組,而不是簡單的delete。

              這并非一個完全的指針指南,其中有一點我能夠涉及到的其它細節(jié),例如指針的指針;還有一些我一點也未涉及到的東西,例如函數(shù)指針——我認為作為初學(xué)者的文章,這個有些復(fù)雜了;還有一些很少使用的東西,在此我亦沒有提到,省得讓這些不實用的細節(jié)使大家感到混亂。

              就這樣了!你可以試著運行本文中的程序,并自己編寫一些示例來弄懂關(guān)于指針的問題吧。

            posted on 2006-02-26 16:19 笑笑生 閱讀(171) 評論(0)  編輯 收藏 引用 所屬分類: C++語言
             
            Copyright © 笑笑生 Powered by: 博客園 模板提供:滬江博客
            18岁日韩内射颜射午夜久久成人| 久久综合给合综合久久| 久久婷婷五月综合色高清 | 久久综合一区二区无码| 久久人人爽人人爽人人片AV东京热| 亚洲成色WWW久久网站| 99热成人精品免费久久| 久久综合久久美利坚合众国| 精品久久一区二区三区| 狠狠色丁香婷婷久久综合五月| 91精品国产综合久久精品| 综合久久精品色| 99久久精品免费看国产| 国产美女亚洲精品久久久综合| 欧美久久精品一级c片片| 国产美女亚洲精品久久久综合| 99久久夜色精品国产网站| 久久婷婷五月综合色高清| 久久精品国产日本波多野结衣| 国产精品永久久久久久久久久 | 亚洲精品乱码久久久久久| 国产精品熟女福利久久AV| 国产精品久久久久天天影视| 久久午夜无码鲁丝片秋霞| 久久久久久国产精品无码下载| 国内精品久久九九国产精品| 亚洲国产精品一区二区久久hs| 欧美久久久久久午夜精品| 2020最新久久久视精品爱| 久久精品国产只有精品2020| 色综合久久久久无码专区| 人妻无码αv中文字幕久久琪琪布| 一本伊大人香蕉久久网手机| 久久久久99精品成人片欧美 | 精品久久久久久久久久中文字幕 | 很黄很污的网站久久mimi色 | 狠狠色噜噜狠狠狠狠狠色综合久久| 久久久久se色偷偷亚洲精品av| 人妻无码久久精品| 怡红院日本一道日本久久| 久久久久久a亚洲欧洲aⅴ|