C/C++中,空數組、空類、類中空數組的解析及其作用

來源:互聯網
上載者:User

標籤:結構   結果   c++   成員   struct   名稱   name   cout   區別   

轉自:http://blog.sina.com.cn/s/blog_93b45b0f01015s95.html

 

我們經常會遇到這些問題:

(1)C++中定義一個空類,他們它的大小(sizeof) 為多少?

(2)只有一個char資料成員的類的大小?

(3)能否定義一個空數組?

(4)空數組名做標示的指標指向什麼地方?

(5)空類有什麼用?

(6)空數組有什麼用?

等等......

這些問題,筆者在這篇文章統統做一個比較詳細的解析和認識。

 

 

1. sizeof是什嗎?

首先我們要理解sizeof是什麼東西?

準確來講,對於C++這種強型別的語言,在某一時刻,對象的類型的大小是確定的,這個資訊在編譯的時候直接可以確定,所以我們要明白sizeof並不是一個函數,而是一個返回物件類型大小的宏,這個宏的參數可以是對象,也可以是類型。

我們需要明白的是,在編譯結束後,sizeof的那個位置上面是直接被替換成一個常數的,我們用一個簡單而直觀的實驗來證實一下:

int main() {

        int a=2;

        int b[sizeof(a)];

        cout<<sizeof(b)/sizeof(int)<<endl;

}

如果sizeof是作為的函數,那麼這個是不可能編譯成功的,因為棧上定義數組是一定需要常數(或常數運算式的)。

這樣我們就能知道:

sizeof(i++);

這樣一句話,i是不可能加1的,因為這句話在編譯的時候就已經被轉換成的對應的常數,而編譯的時候是不會進行啟動並執行,這是常常出現的陷阱之一。

 

 

2. 空類的大小

很多人都知道,一個空類(後者是空類對象)使用sizeof的時候,結果是1。解釋相信大家也知道,想想,如果真是空類。那麼對於同一個空類的對象就不會佔空間,不會佔空間就意味著無法區分。

(有人可能會說,我們只指派至名,不分配空間,那樣的話,你會讓整個C/C++語言為空白類,以及相關的空類對象設計一套特殊的規則,是這個語言變得非常不合理)。

所以,C++的選擇是,自動的給空類插入一個char類型(只一個特殊對待),只要這個類對象將來占空間,那麼就可以通過地址來區分他們。

 

 

3. 空類的作用

還有一個關於空類的疑問就是,C++語言有必要保留空類嗎?空類實現Null 物件有什麼用?

有用的,尤其是在“泛型程式設計”中,空類(結構)的用處非常廣:

在其他的文章中提到,我們利用類型(通常是空類)來區別對待不同類對象的屬性。(其實我們是可以通過使用常數來區分的,但是區別我們很容易就能知道)。

使用常數來區分需要使用if else的這種運行時來確定執行的線路的方法,而使用函數重載的方法,在參數中加入一個空類域作為區分不同的函數的方法,編譯的時候直接選擇,而不是在啟動並執行時候選擇,這是非常提高效率的。

要知道,不同的空類,是不同的。他們代表著不同的類型(雖然他們結構一樣)。在STL中,使用空類區分不同類型的標誌,從而在編譯的時候來對不同的類進行有針對性的最佳化是非常常見的。

template <typename A>

void fun(A a)

{

        typedef typename trait<A>::type T;

        _fun(A a, *(new T()));

}  

template <typename A>

void _fun(A a, int)

{    

        ……

}

template <typename A>

void _fun(A b, float)

{

        ……

}

 

當然,空類應該還有其他的用處。我們所有知道和理解的就是:空類是C++中一個有用的機制,不同名稱的空類代表著不同的類型。

空類在編譯的時候會被編譯器自動的加入一個char成員,不為別的,只是為了,讓它被執行個體後的對象佔有空間,從而可以區分。

 

4. 空數組

C中我們可以定義空數組:

int a[0];

使用sizeof的時候你c猜是多少:

0

好吧,這裡0,我們可以理解。

但是問題就來了:

既然前面對於空類的情況中,因為需要讓對象唯一定位,所以插入char,那麼空數組既然sizeof的大小為0,那應該就是不佔空間,那麼如何區分。

事實上,對於空數組,在C/C++有著特別的交代(可能是具體的實現不同,這裡只是使用GCC,G++)。

空數組名是一個指標,(但是又不佔空間)指向一個位置:

對於結構體中,空數組名這個指標指向了前面一個成員結束的第一個空間。

對於非結構題中,空數組名這個指標指向的內容,與前一個對象的指標的內容一樣(雖然可能他們的類型不一樣)。

雖然,我們不知道這兩種安排有什麼玄機,或者益處,但是無所謂(下一節會介紹空數組的作用),但是針對空數組的sizeof為什麼可以為0,我們有瞭解釋。

 

與空類,不同的是,空數組是一個對象,而不是一個類。既然我們這個對象定義出來了,而且它會指向一個空間(雖然這個空間可能會與其他的地方重疊)但是,我們總算能夠區分開不同的空數組。

 

5. 空數組的作用

其實在C裡面,空數組的使用是非常多的。

問題:

 

假如你想要給一個結構體(代表一個功能)添加一個緩衝區。你會怎麼做?

1)定義一個固定長度的buffer數群組成員,這樣的不好之處在於buffer會被定死。

2)定義一個buffer指標,在建構函式(雖然C沒有,但可以使用initialize函數來代替)中動態建立一個需要大小的buffer,給這個結構體使用。

      但是這樣就需要我們特別管理這個空間(使用解構函式),否則會很容易出現記憶體泄露。並且,一個buffer指標還佔有了一個空間。

 

那麼C裡面,就有一個巧用空數組來達到這個問題的方法。

 

sttuct  T

{

        int a;

        int b;

        ……

        char buffer[];

};

我們知道,由於buffer並不佔空間,所以,T的對象的總大小是不會把buffer算上的。

 

struct T * p=(T*)malloc(sizeof(T) +buffer_len);

看到沒有,在聲請空間的時候,加上buffer_len(所需緩衝區長度),這樣結構體和緩衝區一起被申請了,(在結束的時候,也可以直接使用free一起釋放,可以避免獨立的管理結構體和緩衝區)。

並且我們知道,buffer這個“指標”指向的就是結構體後面的那個buffer_len的空間。

 

這樣做還有一個好處,如果我們分開管理結構體和緩衝區(通常這個時候結構體是一個小片段)。在申請和釋放的時候,很容易在記憶體中製造出片段。

而如果向上面的這樣管理,結構體,依附這緩衝區(大塊)一起被管理。那將是一個很美好的事情。這就是空數組的用處。

 

6. 類中空數組

class T

{

        int a[0];

};

您看這個類的sizeof為多少:

0

你會覺得這像個玩笑,但是其實仔細分析一下,也是可以所通的。

我前面說給一個空類插入一個char成員,是因為想讓程式能夠區分該類的不同對象。

而這裡,我們知道由於空數組是不佔記憶體的,它就像一個指標指向某個地方,但是又不佔記憶體。但是的確我們的類對象能夠藉助空數組這個東西來區分開來。

所以既然目的達到了,那麼為什麼還要加入什麼一些什麼資訊呢?

C/C++中,空數組、空類、類中空數組的解析及其作用

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.