C++this指針詳解


  以前對this指針誤解挺多的,在這里單獨寫一篇進行總結,有不對之處,歡迎指正批評!

一、問題

1.一個類中的不同對象在調用自己的成員函數時,其實它們調用的是同一段函數代碼,那么成員函數如何知道要訪問哪個對象的數據成員呢?

  沒錯,就是通過this指針。每個對象都擁有一個this指針,this指針記錄對象的內存地址,當我們調用成員函數時,成員函數默認第一個參數為T* const register this,大多數編譯器通過ecx寄存器傳遞this指針,通過 this 這個隱式參數可以訪問該對象的數據成員。

2.類的成員函數為什么不能用static和const同時修飾?

  類中用const修飾的函數通常用來防止修改對象的數據成員,函數末尾的const是用來修飾this指針,防止在函數內對數據成員進行修改,而靜態函數中是沒有this指針的,無法訪問到對象的數據成員,與C++ static語義沖突,所以不能。

二、this指針注意點

1.C++中this關鍵字是一個指向對象自己的一個常量指針,不能給this賦值;

2.只有成員函數才有this指針,友元函數不是類的成員函數,沒有this指針;

3.同樣靜態函數也是沒有this指針的,靜態函數如同靜態變量一樣,不屬於具體的哪一個對象;

4.this指針作用域在類成員函數內部,在類外也無法獲取;

5.this指針並不是對象的一部分,this指針所占的內存大小是不會反應在sizeof操作符上的。

三、this指針的使用

1.在類的非靜態成員函數中返回類對象本身的時候,直接使用 return *this,比如類的默認取址運算符重載函數,另外,也可以返回*this的引用,這樣可以像輸入輸出流那樣進行“級聯”操作;

2.修改類成員變量或參數與成員變量名相同時,如this->a = a (寫成a = a編譯不過);

3.在class定義時要用到類型變量自身時,因為這時候還不知道變量名,就用this這樣的指針來使用變量自身。

四、this指針探討

1.this指針是什么時候創建的? 

  對象new的過程中創建的,具體哪個階段有待進一步深入了解。

2. this指針存放在何處?

  this指針會因編譯器不同而有不同的放置位置。可能是棧,也可能是寄存器,甚至全局變量。在匯編級別里面,一個值只會以3種形式出現:立即數、寄存器值和內存變量值。不是存放在寄存器就是存放在內存中,它們並不是和高級語言變量對應的。

3.為什么C++ NULL對象指針可以調用非虛成員函數,而Java中卻不行?

  C++語言是靜態綁定的,這也是C++語言和Java語言的一個顯著區別。類的成員函數並不與特定對象綁定,所有成員函數共用一份成員函數體,當程序編譯后,成員函數的地址即已經確定。另外,C++只關心你的指針類型,不關心指針指向的對象是否有效,C++要求程序員自己保證指針的有效性。況且在有些系統上,地址0也是有效的,理論上完全可以構造一個在地址0上的對象,所以C++中nullptr對象調用成員函數並無不可 。

  nullptr對象調用成員函數時,只要不訪問此對象獨有的內存部分,則程序正常運行,因為不會使用this,一旦訪問此對象的成員變量,則程序崩潰。當然nullptr調用虛方法是不能正常運行的(虛函數有虛表,會占用內存空間),虛方法調用是依賴於this指針的。可以這樣理解,你給函數傳遞了錯誤的參數,但在該函數內部並沒有使用該參數,所以其不影響函數的運行。可以參考下面代碼:

 1 #include <iostream>
 2 using namespace std;
 3 
 4 class CPeople
 5 {
 6 public:
 7     CPeople(const std::string& name, int age)
 8       : mName(name), mAge(age){}
 9      ~CPeople();
10  
11     void Print()
12     {
13         std::cout << "show people info:" << std::endl;
14     }
15 
16     void PrintInfo()
17     {
18         std::cout << "name:" << mName << std::endl;
19         std::cout << "age:" << mAge << std::endl;
20     }
21  
22 private:
23  
24     std::string mName;
25     int mAge;
26  
27 };
28  
29 int main()
30 {
31     CPeople* jon = NULL;
32     jon->Print();  // 程序正常運行
33     jon->PrintInfo();  // 程序崩潰,訪問非法地址,此時mName和mAge並沒有分配空間
34     return 0;
35 }

 

五、總結

  引用網上關於this指針的一個經典回答:

  當你進入一個房子后,
  你可以看見桌子、椅子、地板等,
  但是房子你是看不到全貌了。
  對於一個類的實例來說,
  你可以看到它的成員函數、成員變量,
  但是實例本身呢?
  this是一個指針,它時時刻刻指向你這個實例本身。

  對this指針有了一個全面了解后,是否對C++ class理解也更深刻一步?

  寫作,能讓人更深入的了解事情的本質,慢慢積累,厚積薄發,加油!

 

作者:KeepHopes
出處:https://www.cnblogs.com/yuwanxian/p/10988736.html
關於作者:專注C++,對大數據、人工智能領域頗感興趣,請多多賜教!
本文為作者原創,版權歸作者和博客園共有,轉載或引用請注明出處,謝謝!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM