C++ 中的this指針

C++中的this指針

一個對象的this指針並不是對象本身的一部分,不會影響sizeof(對象)的結果。this作用域是在類內部,當在類的非靜態成員函數中訪問類的非靜態成員的時候,編譯器會自動將對象本身的地址作爲一個隱含參數傳遞給函數。

主要作用:

一個對象的this指針並不是對象本身的一部分,不會影響sizeof(對象)的結果。this作用域是在類內部,當在類的非靜態成員函數中訪問類的非靜態成員的時候,編譯器會自動將對象本身的地址作爲一個隱含參數傳遞給函數。也就是說,即使你沒有寫上this指針,編譯器在編譯的時候也是加上this的,它作爲非靜態成員函數的隱含形參,對各成員的訪問均通過this進行。

例如,調用date.SetMonth(9) <===> SetMonth(&date, 9),this幫助完成了這一轉換 .

使用:

一種情況就是,在類的非靜態成員函數中返回類對象本身的時候,直接使用 return *this;另外一種情況是當參數與成員變量名相同時使用this指針,如this->n = n (不能寫成n = n)。

this指針是類的一個自動生成、自動隱藏的私有成員,它存在於類的非靜態成員函數中,指向被調用函數所在的對象。全局僅有一個this指針,當一個對象被創建時,this指針就存放指向對象數據的首地址。
根據以下程序來說明this指針
#include<iostream>
using namespace std;
class Point
{
private:
intx,y;
public:
Point(int a,int b){
x=a;
y=b;
}
void MovePoint(int a,int b){
x+=a;
y+=b;
}
void print(){
cout<<"x="<<x<<"y="<<y<<endl;
}
};
int main()
{
Point point1(10,10);
point1.MovePoint(2,2);
point1.print();
return 0;
}

對象point1調用MovePoint(2,2)函數時,即將point1對象的地址傳遞給了this指針。
MovePoint函數的原型應該是 void MovePoint( Point *this, int a, int b);第一個參數是指向該類對象的一個指針,我們在定義成員函數時沒看見是因爲這個參數在類中是隱含的。這樣point1的地址傳遞給了this,所以在MovePoint函數中便顯式的寫成:
void MovePoint(int a, int b) { this->x +=a; this-> y+= b;}
即可以知道,point1調用該函數後,也就是point1的數據成員被調用並更新了值。
關於this指針的一個經典回答:
當你進入一個房子後,
你可以看見桌子、椅子、地板等,
但是房子你是看不到全貌了。
對於一個類的實例來說,
你可以看到它的成員函數、成員變量
但是實例本身呢?
this是一個指針,它時時刻刻指向你這個實例本身
使用this指針要注意的事項:
相信大家對指針的用法已經很熟了,這裏也不多說些定義性的東西了,只說一下指針使用中的注意事項吧。
一.在定義指針的時候注意連續聲明多個指針時容易犯的錯誤,例如int * a,b;這種聲明是聲明瞭一個指向int類型變量的指針a和一個int型的變量b,這時候要清醒的記着,而不要混淆成是聲明瞭兩個int型指針。
二.要避免使用未初始化的指針。很多運行時錯誤都是由未初始化的指針導致的,而且這種錯誤又不能被編譯器檢查所以很難被發現。這時的解決辦法就是儘量在使用指針的時候定義它,如果早定義的話一定要記得初始化,當然初始化時可以直接使用cstdlib中定義的NULL也可以直接賦值爲0,這是很好的編程習慣。
三.指針賦值時一定要保證類型匹配,由於指針類型確定指針所指向對象的類型,因此初始化或賦值時必須保證類型匹配,這樣才能在指針上執行相應的操作。
應用參考:

this指針只能在一個類的成員函數中調用,它表示當前對象的地址。下面是一個例子:

voidDate::setMonth(intmn)
{
month=mn;
this->month=mn;
(*this).month=mn;
//這三句是等價的
}

1.this只能在成員函數中使用。
全局函數,靜態函數都不能使用this。
實際上,成員函數默認第一個參數爲T*const register this。
如:
class A{public: int func( int p){}};
其中,func的原型在編譯器看來應該是: int func(A*const register this, int p);
2. 由此可見,this在成員函數的開始前構造的,在成員的結束後清除。
這個生命週期同任一個函數的參數是一樣的,沒有任何區別。
當調用一個類的成員函數時,編譯器將類的指針作爲函數的this參數傳遞進去。如:
A a;
a.func(10);
此處,編譯器將會編譯成: A::func(&a, 10);
嗯,看起來和靜態函數沒差別,對嗎?不過,區別還是有的。編譯器通常會對this指針做一些優化的,因此,this指針的傳遞效率比較高--如vc通常是通過ecx寄存器來傳遞this參數。
3. 回答
#1:this指針是什麼時候創建的?
this在非靜態成員中有意義,作爲右值可以直接在編譯時確定其存在,運行時無所謂創建。
#2:this指針存放在何處?堆,棧,全局變量,還是其他?
由上一問可知,this指針無需顯式儲存內存中。只要存儲對象的內存位置確定,對應的this指針就被確定了。
#3:this指針如何傳遞給類中函數的?綁定?還是在函數參數的首參數就是this指針.那麼this指針又是如何找到類實例後函數的?
this是通過函數參數的首參數來傳遞的。this指針是在調用之前生成的。類實例後的函數,沒有這個說法。類在實例化時,只分配類中的變量空間,並沒有爲函數分配空間。自從類的函數定義完成後,它就在那兒,不會跑的。
#4:this指針如何訪問類中變量的?
如果不是類,而是結構的話,那麼,如何通過結構指針來訪問結構中的變量呢?如果你明白這一點的話,那就很好理解這個問題了。
在C++中,struct是一種類類型,struct和class只有一個區別的:class的成員和繼承默認的訪問控制權限是private,而struct是public。
this是class或public的對象的指針。
#5:我們只有獲得一個對象後,才能通過對象使用this指針,如果我們知道一個對象this指針的位置可以直接使用嗎?
this指針只有在非靜態成員中才有意義。獲得一個對象後,不需要在類外部使用this對其操作。應當注意this是一個右值(方法的一個隱式參數)[2] ,不存在所謂的this的“位置”,只是this表示了對象的存儲位置而已。&this違反語義規則,是錯誤的用法,不會編譯通過。
#6:每個類編譯後,是否創建一個類中函數表保存函數指針,以便用來調用函數?
一般來說,對於類成員函數(不論是靜態還是非靜態的成員函數)都不需要創建一個在運行時的函數表來保存。只有虛函數纔會被放到函數表中。
但是,即使是虛函數,如果編譯器能明確知道調用的是哪個函數,編譯器就不會通過函數表中的指針來間接調用,而是可以直接調用該函數。[3] 

發佈了25 篇原創文章 · 獲贊 18 · 訪問量 16萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章