C++學(xué)習(xí)進階篇之類大小計算和this指針
一、類大小計算
類的大小是只計算它的成員變量或者自定義成員,不會計算它的成員函數(shù)大小。
#include<iostream> using namespace std; class A1 { public: void fun() { _a = 1; _b = 2; } int _a; int _b; }; int main() { cout << sizeof(A1) << endl;//8字節(jié),為何是8字節(jié) return 0; }
光是類中成員變量_a,_b所占的字節(jié)大小就為8了,但是類中還要成員函數(shù),為何還是8字節(jié) 難道成員函數(shù)沒有在類之中,對的
類成員函數(shù)在公共代碼區(qū)的,不同對象的成員數(shù)據(jù)是私有的每個人有自己的成員數(shù)據(jù)
但是成員函數(shù)是共有的,此時別人也可以用,所有它們并不是都要有成員函數(shù)成員函數(shù)反而占用更多的空間
類定義對象之后,相當(dāng)于小區(qū)房子,每個房子都有廚房,臥室(相當(dāng)于數(shù)據(jù))
但是這些房子不一定要有籃球場(相當(dāng)于成員函數(shù)),如果每一個房子都有籃球場可想而知這個房子占地會有多大
其次籃球場得很多人來玩籃球澀,不可能每次都是你一個人玩,無不無聊,得喊朋友鄰居一起,這些朋友鄰居也能玩
還不如將其修在小區(qū)中心,這樣大大節(jié)省了空間 而類它的成員函數(shù)就是放在公共代碼區(qū)的,所以不占用類空間大小
空類或者只有成員函數(shù)時,類大???
1字節(jié)大小,它占個位,雖然一個房子它可能什么都么有但是它難道就不是房子了嗎,起碼那塊地還是一個房子,理應(yīng)有一個位置
#include<iostream> using namespace std; class A1//類中只有成員函數(shù) { void fun() {} }; class A2 {};//空類 int main() { cout << sizeof(A1) << endl; cout << sizeof(A2) << endl; A1 a; A2 b; //雖然里面什么都沒有但是這個位置是要在的 cout << &a << endl; cout << &b << endl; return 0; }
沒有成員變量的類對象,需要1byte是為了占位,表示對象存在
二、this指針
作為成員函數(shù)的隱形指針,接收對象地址
#include<iostream> using namespace std; class day { public: void init(int year, int month, int day) { _year = year; _month = month; _day = day; } void Print() { //cout << this->_year << '-' << this->_month << '-' << this->_day << endl; cout << _year << '-' <<_month << '-' << _day << endl; } int _year; int _month; int _day; }; int main() { day d1; day d2; d1.init(2023, 4, 24); d2.init(2022, 4, 24); d1.Print(); d2.Print(); return 0; }
雖然兩個對象初始化不同,但是我在調(diào)用打印函數(shù)時,實參可是什么都沒傳,都是call同一個地址,為何結(jié)果卻不同?
既然類中的成員函數(shù)是放在公共代碼區(qū)的,不在對象總,這個函數(shù)的地址是固定的,
那么為何兩個對象調(diào)用它(函數(shù))時所得結(jié)果會不一樣(都是call同一個地址)
是因為對象在調(diào)用時編譯器隱含的將對象的地址作為實參給傳了過去,而函數(shù)形參隱含用this指針接收 在調(diào)用時,默認(rèn)將對象地址當(dāng)作實參傳過去
調(diào)試程序,然后右擊鼠標(biāo),點擊轉(zhuǎn)到反匯編,查看匯編代碼
這些匯編代碼是在將實參壓棧
可以發(fā)現(xiàn)原本調(diào)用成員函數(shù)Init時只是顯式傳了三個實參,但是在底層匯編指令卻壓了四個參數(shù),那是因為將對象的地址作為實參隱含壓棧
在壓棧時,會將對象的地址作為實參壓棧傳給它所調(diào)用的成員函數(shù)
在vs下面,對this指針傳遞進行了優(yōu)化,將對象的地址放在寄存器(rcx)中,寄存器(rcx)存this指針的值
Print這里有隱含對象形參指針的,但是不能將其顯式的寫出來
不可修改this指針指向的對象,因為this是被const修飾(相當(dāng)于day*const this
)它的指向?qū)ο蟛豢杀恍薷?br />但是它指向?qū)ο蟮膬?nèi)容可以被修改
也可以通過this指針訪問對象成員變量
雖然成員函數(shù)形參this指針不能顯式寫出
但是在成員函數(shù)內(nèi)要訪問對象中成員變量時卻可以顯示寫出
可不可以這樣訪問類的成員變量?
不可這樣直接訪問,就算是類所以成員都是對外開放的,但是類中的成員變量只是聲明了,并沒有將其實例化,相當(dāng)于房子,只拿著一張圖紙,你就想在現(xiàn)實世界找到對應(yīng)的房間,抱歉不可能
那么可不可以這樣直接調(diào)用類的成員函數(shù)?
這種直接在類中調(diào)用它的成員函數(shù),其實是不行的,因為這都沒有定義出對象,編譯器在調(diào)用Print函數(shù)時是會隱晦的將對象地址當(dāng)作實參傳過去,這里連對象都沒有如何調(diào)用?
那么有人又會說,那我傳空地址可否?在調(diào)用時,對象地址是隱晦的壓棧,并不能顯式的寫出來,也是不行的
#include<iostream> using namespace std; class day { public: void init(int year, int month, int day) { _year = year; _month = month; _day = day; } void Print() { cout << this->_year << '-' << this->_month << '-' << this->_day << endl; } int _year; int _month; int _day; }; int main() { day* p = nullptr; p->init(2023, 4, 24); p->Print(); }
p->initp調(diào)用函數(shù)init會對這個函數(shù)解引用嗎?不會,因為這個函數(shù)的地址不在這個對象中,它在公共代碼區(qū) p會作為實參傳給this指針
雖然定義類對象是為空的指針,但是調(diào)用類成員初始化函數(shù),并沒有報錯,是因為沒有訪問對象中的成員變量
這樣會發(fā)生錯誤,因為訪問對象中的成員,但是this指針的值為空,對空指針解引用,這樣極其危險的操作
總結(jié)
到此這篇關(guān)于C++學(xué)習(xí)進階篇之類大小計算和this指針的文章就介紹到這了,更多相關(guān)C++類大小計算和this指針內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C++實現(xiàn)LeetCode(109.將有序鏈表轉(zhuǎn)為二叉搜索樹)
這篇文章主要介紹了C++實現(xiàn)LeetCode(109.將有序鏈表轉(zhuǎn)為二叉搜索樹),本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-07-07vc中float與DWORD的互想轉(zhuǎn)換實現(xiàn)代碼
這篇文章主要介紹了vc中float與DWORD的互想轉(zhuǎn)換實現(xiàn)代碼,需要的朋友可以參考下2017-06-06C語言中計算正弦的相關(guān)函數(shù)總結(jié)
這篇文章主要介紹了C語言中計算正弦的相關(guān)函數(shù)總結(jié),包括正弦和雙曲線正弦以及反正弦的函數(shù),需要的朋友可以參考下2015-08-08C++實現(xiàn)獲取IP、子網(wǎng)掩碼、網(wǎng)關(guān)、DNS等本機網(wǎng)絡(luò)參數(shù)的方法
這篇文章主要介紹了C++實現(xiàn)獲取IP、子網(wǎng)掩碼、網(wǎng)關(guān)、DNS等本機網(wǎng)絡(luò)參數(shù)的方法,需要的朋友可以參考下2014-07-07