欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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

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

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

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

實驗的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調試功能的反匯編代碼

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 /*構造函數(shù)中的實參值: 10 */
00A418A2 lea   ecx,[s] /*取實例s的內存地址,并賦值給寄存器ECX*/
00A418A5 call  Student::Student (0A4103Ch) /*調用位于內存地址0A4103Ch的構造函數(shù)*/
 int age = s.getAge();
00A418AA lea   ecx,[s] /*取實例s的內存地址,并賦值給寄存器ECX*/
00A418AD call  Student::getAge (0A412D5h) /*調用位于內存地址0A412D5h的成員函數(shù)*/
00A418B2 mov   dword ptr [age],eax /*成員函數(shù)的返回值賦給變量age*/
 
 Student* ps = new Student(10);
00A418B5 push  4 /*類實例所需的內存大小,有一個int類型成員,故為4字節(jié)(32位編譯)*/
00A418B7 call  operator new (0A412A3h) /*調用全局的內存分配函數(shù),類似C的malloc函數(shù)*/
00A418BC add   esp,4 /*棧頂加4個字節(jié),用于保存operator new內存分配返回的內存地址值*/
00A418BF mov   dword ptr [ebp-108h],eax /*eax存的就是返回的內存地址,賦值到ptr [ebp-108h]這是處于棧中的內存*/
00A418C5 mov   dword ptr [ebp-4],0 
00A418CC cmp   dword ptr [ebp-108h],0 
00A418D3 je   main+8Ah (0A418EAh) /*與上一句聯(lián)動,如果分配的地址為0,即失敗,跳轉到0A418EAh*/
00A418D5 push  0Ah /*調用構造函數(shù)的實參值: 10*/
00A418D7 mov   ecx,dword ptr [ebp-108h] /*取指針ps指向的實例的內存地址值并賦值給寄存器ECX*/
00A418DD call  Student::Student (0A4103Ch) /*調用位于內存地址 0A4103Ch 的構造函數(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的內存地址值并賦值給寄存器ECX*/
00A41913 call  Student::getAge (0A412D5h) /*調用位于內存地址 0A412D5h 的成員函數(shù)*/
 age = ps->getAge();
00A41918 mov   dword ptr [age],eax 
 
 return 0;
00A4191B xor   eax,eax 
}

分析

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

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

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

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

回歸標題

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

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

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;
}

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

最后發(fā)散思考

回想其中一句話:成員函數(shù)是屬于類的,而不屬于實例的,會不會引發(fā)你的思考,類的靜態(tài)函數(shù),也是屬于類的, 那如果用類的空指針調用靜態(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ù),所以這種調用是安全的。但在實際編程中, 這個方法應該不會被使用到吧(個人觀點,用類名調用它不香嗎,還有去寫一個類指針再調用)

總結

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

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

相關文章

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

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

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

    有關C++頭文件的包含順序研究

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

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

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

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

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

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

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

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

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

    C++預處理連接的示例詳解

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

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

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

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

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

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

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

最新評論