亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

C++類的空指針調(diào)用成員函數(shù)的代碼

 更新時間:2020年07月30日 17:19:18   作者:革昨日之我  
這篇文章主要介紹了C++類的空指針調(diào)用成員函數(shù),本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下

類的實例調(diào)用成員函數(shù)的原理

其實不管是通過對象實例或指針實例調(diào)用,其實底層調(diào)用的過程都是一樣的,都是把當前對象的指針作為一個參數(shù)傳遞給被調(diào)用的成員函數(shù)。通過下面的相關(guān)實例代碼進行檢驗:

實驗的C++代碼

class Student
{
private:
 int age;
public:
 Student() {}
 Student(int age) : age(age) {}
 int getAge() { return this->age; }
};
 
int main(int argc, char const *argv[])
{
 Student s(10);
 int age = s.getAge();
 
 Student* ps = new Student(10);
 age = ps->getAge();
 
 return 0;
}

基于VS2015調(diào)試功能的反匯編代碼

int main(int argc, char const *argv[])
{
00A41860 push  ebp 
00A41861 mov   ebp,esp 
00A41863 push  0FFFFFFFFh 
00A41865 push  0A461D2h 
00A4186A mov   eax,dword ptr fs:[00000000h] 
00A41870 push  eax 
00A41871 sub   esp,104h 
00A41877 push  ebx 
00A41878 push  esi 
00A41879 push  edi 
00A4187A lea   edi,[ebp-110h] 
00A41880 mov   ecx,41h 
00A41885 mov   eax,0CCCCCCCCh 
00A4188A rep stos dword ptr es:[edi] 
00A4188C mov   eax,dword ptr [__security_cookie (0A4B004h)] 
00A41891 xor   eax,ebp 
00A41893 mov   dword ptr [ebp-10h],eax 
00A41896 push  eax 
00A41897 lea   eax,[ebp-0Ch] 
00A4189A mov   dword ptr fs:[00000000h],eax 
 Student s(10);
00A418A0 push  0Ah /*構(gòu)造函數(shù)中的實參值: 10 */
00A418A2 lea   ecx,[s] /*取實例s的內(nèi)存地址,并賦值給寄存器ECX*/
00A418A5 call  Student::Student (0A4103Ch) /*調(diào)用位于內(nèi)存地址0A4103Ch的構(gòu)造函數(shù)*/
 int age = s.getAge();
00A418AA lea   ecx,[s] /*取實例s的內(nèi)存地址,并賦值給寄存器ECX*/
00A418AD call  Student::getAge (0A412D5h) /*調(diào)用位于內(nèi)存地址0A412D5h的成員函數(shù)*/
00A418B2 mov   dword ptr [age],eax /*成員函數(shù)的返回值賦給變量age*/
 
 Student* ps = new Student(10);
00A418B5 push  4 /*類實例所需的內(nèi)存大小,有一個int類型成員,故為4字節(jié)(32位編譯)*/
00A418B7 call  operator new (0A412A3h) /*調(diào)用全局的內(nèi)存分配函數(shù),類似C的malloc函數(shù)*/
00A418BC add   esp,4 /*棧頂加4個字節(jié),用于保存operator new內(nèi)存分配返回的內(nèi)存地址值*/
00A418BF mov   dword ptr [ebp-108h],eax /*eax存的就是返回的內(nèi)存地址,賦值到ptr [ebp-108h]這是處于棧中的內(nèi)存*/
00A418C5 mov   dword ptr [ebp-4],0 
00A418CC cmp   dword ptr [ebp-108h],0 
00A418D3 je   main+8Ah (0A418EAh) /*與上一句聯(lián)動,如果分配的地址為0,即失敗,跳轉(zhuǎn)到0A418EAh*/
00A418D5 push  0Ah /*調(diào)用構(gòu)造函數(shù)的實參值: 10*/
00A418D7 mov   ecx,dword ptr [ebp-108h] /*取指針ps指向的實例的內(nèi)存地址值并賦值給寄存器ECX*/
00A418DD call  Student::Student (0A4103Ch) /*調(diào)用位于內(nèi)存地址 0A4103Ch 的構(gòu)造函數(shù)*/
00A418E2 mov   dword ptr [ebp-110h],eax 
00A418E8 jmp   main+94h (0A418F4h) 
00A418EA mov   dword ptr [ebp-110h],0 
00A418F4 mov   eax,dword ptr [ebp-110h] 
00A418FA mov   dword ptr [ebp-0FCh],eax 
00A41900 mov   dword ptr [ebp-4],0FFFFFFFFh 
00A41907 mov   ecx,dword ptr [ebp-0FCh] 
00A4190D mov   dword ptr [ps],ecx 
 age = ps->getAge();
00A41910 mov   ecx,dword ptr [ps] /*取實例s的內(nèi)存地址值并賦值給寄存器ECX*/
00A41913 call  Student::getAge (0A412D5h) /*調(diào)用位于內(nèi)存地址 0A412D5h 的成員函數(shù)*/
 age = ps->getAge();
00A41918 mov   dword ptr [age],eax 
 
 return 0;
00A4191B xor   eax,eax 
}

分析

通過源碼與匯編代碼的對比,就可以知道,其實成員函數(shù)與類的實例是沒有綁定關(guān)系,成員函數(shù)是屬于類的,在內(nèi)存中僅僅只是一個有效的內(nèi)存地址。對于成員函數(shù)中需要用到實例,就通過寄存器ECX傳遞過來。

這里引起一下思考,為什么不通過棧傳遞呢?

首先要明白,棧是位于內(nèi)存的,而寄存器是位于CPU的,這二者的讀寫速率就天差地別了, 這是效率的優(yōu)化;而且只要約定處于當前成員函數(shù)中時,不對ECX寄存器進行修改就好。

但如果使用棧進行傳遞,因為棧是一個動態(tài)的內(nèi)存空間,這就不便于跟蹤與維護當前實例的地址,就算是使用EBP和ESP去維護,就需要加上一個偏移量,這對讀寫效率添加了負擔。如果維護不好,還會造成數(shù)據(jù)錯亂。(這里都是個人分析, 有錯可以指正)

回歸標題

所以回歸到標題,如果一個類的空指針調(diào)用了成員函數(shù)后,編譯是通過的。接著在運行過程中,分兩種情況:

一、當被調(diào)用的成員函數(shù)中,未使用this指針去調(diào)用當前實例的成員變量,程序正常運行不報錯;

class Student
{
private:
 int age;
public:
 Student() {}
 Student(int age) : age(age) {}
 void eat() {}
};
 
int main(int argc, char const *argv[])
{
 Student* ps = nullptr;
 ps->eat();
 return 0;
}

二、當被調(diào)用的成員函數(shù)中,使用了this指針去讀寫當前實例的成員變量時,首先調(diào)用是成員函數(shù)是被成功調(diào)用的,代碼的執(zhí)行已經(jīng)進入了成員函數(shù)的領(lǐng)空,但當代碼執(zhí)行到讀寫當前實例的成員變量里,就會報內(nèi)存訪問異常了。

最后發(fā)散思考

回想其中一句話:成員函數(shù)是屬于類的,而不屬于實例的,會不會引發(fā)你的思考,類的靜態(tài)函數(shù),也是屬于類的, 那如果用類的空指針調(diào)用靜態(tài)函數(shù),又會發(fā)生什么事呢?上代碼:

#include <iostream>
using namespace std;
 
class Student
{
private:
 int age;
public:
 Student() {}
 Student(int age) : age(age) {}
 static int classtime() {
  return 9;
 }
 void eat() {}
};
 
int main(int argc, char const *argv[])
{
 Student* ps = nullptr;
 int time = ps->classtime();
 cout << time << endl;
 return 0;
}

經(jīng)過實驗就會發(fā)現(xiàn)這代碼是可以成功運行的。其實原理上面都說了, 這里就不贅述了。主要的一點是類的靜態(tài)函數(shù)絕對不會操作到某一實例的成員數(shù)據(jù),所以這種調(diào)用是安全的。但在實際編程中, 這個方法應(yīng)該不會被使用到吧(個人觀點,用類名調(diào)用它不香嗎,還有去寫一個類指針再調(diào)用)

總結(jié)

面試的時候被問到了, 自己會, 但不能回答清晰也是罪,所以在這里總結(jié)一下??!

到此這篇關(guān)于C++類的空指針調(diào)用成員函數(shù)的文章就介紹到這了,更多相關(guān)C++類空指針調(diào)用成員函數(shù)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C++實現(xiàn)簡易五子棋游戲

    C++實現(xiàn)簡易五子棋游戲

    這篇文章主要為大家詳細介紹了C++實現(xiàn)簡易五子棋游戲,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-07-07
  • 有關(guān)C++頭文件的包含順序研究

    有關(guān)C++頭文件的包含順序研究

    下面小編就為大家?guī)硪黄嘘P(guān)C++頭文件的包含順序研究。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-01-01
  • C語言基礎(chǔ)使用IDE快速開發(fā)的方法

    C語言基礎(chǔ)使用IDE快速開發(fā)的方法

    這篇文章主要介紹了C語言基礎(chǔ)使用IDE快速開發(fā)的方法,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-11-11
  • C語言開發(fā)簡易版掃雷小游戲

    C語言開發(fā)簡易版掃雷小游戲

    本文給大家分享的是一個使用C語言開發(fā)的命令行下的簡易版掃雷小游戲,本身沒有什么太多的技術(shù)含量,只不過是筆者的處女作,所以還是推薦給大家,希望對大家學(xué)習(xí)C能夠有所幫助。
    2015-12-12
  • C++函數(shù)指針和回調(diào)函數(shù)使用解析

    C++函數(shù)指針和回調(diào)函數(shù)使用解析

    這篇文章主要為大家詳細介紹了C++函數(shù)指針和回調(diào)函數(shù)的使用,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-10-10
  • C++多重繼承引發(fā)的重復(fù)調(diào)用問題與解決方法

    C++多重繼承引發(fā)的重復(fù)調(diào)用問題與解決方法

    這篇文章主要介紹了C++多重繼承引發(fā)的重復(fù)調(diào)用問題與解決方法,結(jié)合具體實例形式分析了C++多重調(diào)用中的重復(fù)調(diào)用問題及相應(yīng)的解決方法,需要的朋友可以參考下
    2018-05-05
  • C++預(yù)處理連接的示例詳解

    C++預(yù)處理連接的示例詳解

    C++預(yù)處理連接(Preprocessor?Concatenation)是一種宏定義技巧,用于將兩個或多個符號(如變量、字符串等)連接成一個符號。這篇文章主要通過一些示例為大家講解一下預(yù)處理連接,需要的可以參考一下
    2023-03-03
  • C語言數(shù)據(jù)結(jié)構(gòu)之鏈隊列的基本操作

    C語言數(shù)據(jù)結(jié)構(gòu)之鏈隊列的基本操作

    這篇文章主要為大家介紹了C語言之鏈隊列的基本操作,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2021-12-12
  • C++中函數(shù)的用法小結(jié)

    C++中函數(shù)的用法小結(jié)

    這篇文章主要為大家分享下本人在閱讀《C++ Primer》函數(shù)一章時的讀書總結(jié),需要的朋友可以參考下
    2014-02-02
  • 用代碼和UML圖化解設(shè)計模式之橋接模式的深入分析

    用代碼和UML圖化解設(shè)計模式之橋接模式的深入分析

    本篇文章是對橋接模式進行了詳細的分析介紹,需要的朋友參考下
    2013-05-05

最新評論