青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

Impossible is nothing  
  愛過知情重醉過知酒濃   花開花謝終是空   緣份不停留像春風來又走   女人如花花似夢
公告
日歷
<2025年9月>
31123456
78910111213
14151617181920
21222324252627
2829301234
567891011
統計
  • 隨筆 - 8
  • 文章 - 91
  • 評論 - 16
  • 引用 - 0

導航

常用鏈接

留言簿(4)

隨筆分類(4)

隨筆檔案(8)

文章分類(77)

文章檔案(91)

相冊

搜索

  •  

最新評論

閱讀排行榜

評論排行榜

 

何為指針?

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

開始

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

到現在都學到什么了(一個例子):

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

陷阱!

  看看你是否能指出以下程序的缺陷:
#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);
}
   這個程序首先調用SomeFunction函數,在其中創建了一個名為nNumber的變量,并且使pPointer指向這個變量。那么,這就是問題之 所在了。當函數結束的時候,由于nNumber是一個本地變量,那么它就會被銷毀。這是因為當語句塊結束的時候,塊中定義的本地變量都會被銷毀。這就意味 著當SomeFunction返回到main()的時候,那個變量就已經被銷毀了,所以pPointer將會指向一個不再屬于本程序的內存位置。如果你不 懂這一點,那么你應該去讀一讀有關本地變量、全局變量以及作用域的東西,這些概念非常重要。
  那么,如何解決這個問題呢?答案是使用一種名為動態分配的技術。請注意:在這一點上,C和C++是不同的。既然大多數開發者正在使用C++,那么下面的代碼就使用C++來編寫。

動態分配

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

來得明白,去得明白

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

  唯一的一行不同也就是最本質的一點。如果你不將內存delete掉,你的程序就會得到一個“內存泄漏”。如果出現了內存泄漏,那么除非你關閉應用程序,否則你將無法重新使用這段泄漏的內存。

向函數傳遞指針

  向函數傳遞指針的技術非常有用,但是它很容易掌握(譯注:這里存在必然的轉折關系嗎?呃,我看不出來,但是既然作者這么寫了,我又無法找出一個合適的關聯詞,只好按字面翻譯了)。如果我們要編寫一段程序,在其中要把一個數增加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是傳遞到這個函數中的nMyNumber的一份拷貝,而不是nMyNumber本身。因此, “Number = Number + 5”這一行則是向這份拷貝加上了5,而main()中的原始變量并沒有任何變化。你可以運行這個程序試著證明這一點。
  對于這個程序,我們可以 向函數傳遞這個數字內存地址的指針。這樣,我們就需要修改這個函數,使之能接收一個指向整數的指針。于是,我們可以添加一個星號,即把“void AddFive(int Number)”改為“void AddFive(int* Number)”。下面是這個修改過了的程序,注意到我們已經將nMyNumber的地址(而不是它本身)傳遞過去了嗎?此處改動是添加了一個 “&”符號,它讀作(你應該回憶起來了)“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函數中Number之前的“*”的重要性了嗎?這就是告知編譯器我們要在指針Number指向的數字上加5,而不是向指針本身加5。
  最后要注意的一點是,你亦可以在函數中返回指針,像下面這個樣子:
int * MyFunction();
  在這個例子中,MyFunction返回了一個指向整數的指針。

指向類的指針

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

  然后,你可以定義一個MyClass的變量:
MyClass thing;
  你應該已經知道這些了,如果還沒有的話,你需要閱讀一下這方面的資料。你可以這樣定義一個指向MyClass的指針:
MyClass *thing;
  就像你期望的一樣。然后,你可以為這個指針分配一些內存:
thing = new MyClass;
   這就是問題之所在了——你將如何使用這個指針?呃,通常你會這么寫:“thing.m_Number”,但是對于這個例子不行,因為thing并非一個 MyClass,而是一個指向MyClass的指針,所以它本身并不包含一個名為“m_Number”的變量;它指向的結構才包含這個m_Number。 因此,我們必須使用一種不同的轉換方式。這就是將“.”(點)替換為一個“->”(橫線和一個大于號)。請看下面這個例子:
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;
}

指向數組的指針

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

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

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

使用指向數組的指針

  如果你有一個指向數組的指針,你將如何使用它?呃,假如說,你有一個指向整數數組的指針吧。這個指針最初將會指向數組的第一個值,看下面這個例子:
#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++。我們也可以——當然你們有些人可能也猜到了——使用pArray + 2,這將使這個數組指針移動兩個元素。要注意的一點是,你必須清楚數組的上界是多少(在本例中是3),因為在你使用指針的時候,編譯器不能檢查出來你是否 已經移出了數組的末尾。所以,你可能很容易地使系統崩潰。下面仍然是這個例子,顯示了我們所設置的三個值:
#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當前位置的前兩個元素。不過,請確定你是在操作指針,而不是操作它指向的值。這種使用指針的操作在循環的時候非常有用,例如for或while循環。
  請注意,如果你有了一個指針(例如int* pNumberSet),你也可以把它看作一個數組。比如pNumberSet[0]相當于*pNumberSet,pNumberSet[1]相當于*(pNumberSet + 1)。
  關于數組,我還有最后一句警告。如果你用new為一個數組分配空間的話,就像下面這個樣子:
int *pArray;
pArray = new int[6];

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

最后的話

  最后要注意的是:你不能delete掉那些沒有用new分配的內存,像下面這個樣子:
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的區別是什么?
  A:new是C++特有的關鍵詞,并且是標準的分配內存方法(除了Windows程序的內 存分配方法之外)。你絕不能在一個C C++程序中使用malloc,除非絕對必要。由于malloc并不是為C++面向對象的特色設計的,所以使用它為類對象分配內存就不會調用類的構造函 數,這樣就會出現問題。由于這些原因,本文并不對它們進行討論,并且只要有可能,我亦會避免使用它們。

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

引用

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

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

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

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

總結

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

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

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

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

posted on 2006-02-26 16:19 笑笑生 閱讀(184) 評論(0)  編輯 收藏 引用 所屬分類: C++語言
 
Copyright © 笑笑生 Powered by: 博客園 模板提供:滬江博客
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            在线视频亚洲一区| 亚洲国产老妈| 韩国成人福利片在线播放| 国产精品久久久久三级| 欧美少妇一区二区| 国产精品v片在线观看不卡| 欧美日韩三级在线| 国产精品户外野外| 国产欧美日韩精品专区| 国产网站欧美日韩免费精品在线观看 | 欧美一级夜夜爽| 性亚洲最疯狂xxxx高清| 欧美在线免费观看| 久久中文字幕导航| 欧美日本一道本在线视频| 欧美日韩在线亚洲一区蜜芽| 国产日韩一区二区| 99re国产精品| 久久久久久久国产| 亚洲精品激情| 欧美一区二区三区在线看 | 亚洲欧美日韩高清| 玖玖综合伊人| 99国产精品一区| 久久黄色影院| 91久久线看在观草草青青| 亚洲欧美韩国| 欧美国产精品v| 国产亚洲精品高潮| 亚洲一区黄色| 欧美激情在线狂野欧美精品| 亚洲一区二区欧美日韩| 欧美韩日视频| 在线不卡中文字幕| 久久超碰97中文字幕| 亚洲日本中文字幕免费在线不卡| 欧美一区2区三区4区公司二百| 欧美精品乱码久久久久久按摩| 国模吧视频一区| 亚洲男人的天堂在线观看 | 一区二区三区国产| 久久亚洲不卡| 国产视频在线观看一区二区| 亚洲电影视频在线| 欧美性一二三区| 黄色国产精品一区二区三区| 亚洲午夜av电影| 亚洲国产精品va在看黑人| 午夜宅男久久久| 你懂的国产精品| 亚洲国产精品久久人人爱蜜臀| 久久一区二区三区av| 亚洲欧洲一区二区三区| 久久精品99无色码中文字幕| 国产精品免费看片| 亚洲一区欧美一区| 一区二区激情| 欧美日韩在线播放一区| 一区二区三区www| 亚洲九九精品| 欧美香蕉大胸在线视频观看| 亚洲一区影音先锋| 亚洲午夜av在线| 国产精品久久久久久久久| 亚洲一级在线观看| 亚洲视频一区在线观看| 国产日本亚洲高清| 久久永久免费| 欧美高清视频一二三区| 一区二区三区日韩在线观看| 在线亚洲激情| 国语自产精品视频在线看抢先版结局 | 欧美激情一区二区三区成人| 亚洲人精品午夜| 日韩视频在线永久播放| 国产精品久久久对白| 午夜日韩在线观看| 久久高清国产| 亚洲精品美女久久久久| 夜夜精品视频| 国产亚洲福利一区| 欧美国产日韩一区二区| 欧美日韩综合在线| 久久免费黄色| 欧美激情中文字幕一区二区| 亚洲一区二区视频在线观看| 欧美在线3区| 一二三四社区欧美黄| 小嫩嫩精品导航| 亚洲毛片在线观看.| 亚洲一卡久久| 亚洲国产你懂的| 亚洲神马久久| 亚洲精品国偷自产在线99热| 亚洲女同精品视频| 亚洲三级国产| 亚洲欧美日韩区| 日韩视频永久免费| 欧美中文字幕在线视频| 开元免费观看欧美电视剧网站| 亚洲电影免费观看高清完整版在线 | 午夜精品国产更新| 亚洲国产aⅴ天堂久久| 一级成人国产| 亚洲欧洲一区二区天堂久久| a4yy欧美一区二区三区| 在线观看成人网| 亚洲宅男天堂在线观看无病毒| 最新精品在线| 久久精品亚洲一区二区三区浴池| 亚洲私人影院在线观看| 另类国产ts人妖高潮视频| 欧美一二三视频| 欧美三级电影网| 亚洲国产欧美国产综合一区| 国语精品中文字幕| 亚洲综合色激情五月| 亚洲少妇一区| 欧美精品一区二区三区蜜桃 | 亚洲先锋成人| 一区二区三区欧美日韩| 欧美高清免费| 亚洲国产裸拍裸体视频在线观看乱了 | 亚洲视频欧美视频| 农村妇女精品| 欧美成人免费全部观看天天性色| 国产精品一区二区在线| 一本一本a久久| 亚洲色图综合久久| 欧美日韩一区成人| 亚洲人屁股眼子交8| 亚洲国产高清高潮精品美女| 久久久www成人免费毛片麻豆| 欧美在线免费看| 国产一区二区三区在线观看精品 | 亚洲电影免费在线观看| 亚洲高清激情| 欧美国产日本韩| 亚洲精品一区在线观看香蕉| 中国成人黄色视屏| 欧美色精品天天在线观看视频| 亚洲日本中文字幕| 亚洲视频你懂的| 国产精品日韩精品| 午夜精品av| 男女精品视频| 亚洲美女中文字幕| 欧美啪啪成人vr| 亚洲综合国产激情另类一区| 久久er99精品| 亚洲激情影视| 欧美性一区二区| 亚洲小说春色综合另类电影| 99re6热在线精品视频播放速度| 牛牛精品成人免费视频| 亚洲精品四区| 欧美一区二区三区电影在线观看| 国产欧美欧美| 久久综合色一综合色88| 亚洲黄页视频免费观看| 亚洲一二三区在线观看| 国产一区二区福利| 欧美成人xxx| 亚洲视频www| 女生裸体视频一区二区三区| 日韩视频第一页| 国产精品日韩一区二区| 久久综合色婷婷| 亚洲一二三区精品| 麻豆成人综合网| 亚洲先锋成人| 精品999网站| 国产精品国产三级国产aⅴ9色| 久久国产精品一区二区三区四区| 亚洲国产精品一区在线观看不卡| 午夜性色一区二区三区免费视频 | 精品成人国产在线观看男人呻吟| 欧美国产精品劲爆| 欧美一区二粉嫩精品国产一线天| 久久综合九色综合欧美狠狠| 夜夜嗨av一区二区三区四区| 国内精品免费在线观看| 欧美色区777第一页| 免费在线欧美视频| 久久精品91| 一区二区三区欧美视频| 亚洲丁香婷深爱综合| 久久精品国产综合精品| 亚洲色图综合久久| 亚洲日本免费电影| 在线观看成人一级片| 国产在线成人| 国产午夜亚洲精品羞羞网站| 欧美日韩中国免费专区在线看| 麻豆国产精品va在线观看不卡| 欧美亚洲视频在线看网址| 亚洲一区二区少妇| 亚洲视频第一页| 一本一本久久| 中日韩在线视频|