1. 程式人生 > 其它 >C++篇:第七章_結構體、共用體和列舉_知識點大全

C++篇:第七章_結構體、共用體和列舉_知識點大全

  • C++篇為本人學C++時所做筆記(特別是疑難雜點),全是硬貨,雖然看著枯燥但會讓你收益頗豐,可用作學習C++的一大利器

七、結構體、共用體和列舉

(一)結構體

  1. C++的結構體中可以有建構函式,例:

    struct ListNode {
    
    int val;
    
    ListNode *next;
    
    ListNode(int x) : val(x),next(NULL) {}
    
    };
    
  2. class中的成員預設都是private的,結構體中的成員預設都是public的

  3. 結構體型別是可以使用者自定義和宣告的,因此,結構體的型別應該是無數多種

4. 結構體變數的操作:

① 可以將一個結構體變數的值賦給另一個具有相同結構的結構體變數

② 只有結構變數的成員可以進行運算,變數之間不可以進行運算

③ 不能將一個結構體變數作為一個整體進行輸入和輸出,只能對結構體物件中的成員逐個進行輸入或輸出;例:student1和student2為結構體變數,並且它們已有值。不能cin>>student1;只能對結構體變數中的各個成員分別進行輸入和輸出

  1. 所有的成員在分配記憶體時都要與所有成員中佔記憶體最多的資料型別所佔記憶體空間的位元組數對齊,例:最長的資料型別佔 4 位元組,所以是以 4 對齊

  2. struct 能包含成員函式,能繼承,能實現多型,可以有無參建構函式,和class的區別在於預設訪問控制型別不同

  3. struct成員型別不可以是它自己,因為會遞迴定義,理論上這樣導致結構體的大小不能被計算(無限大小)。所以不能在結構體裡的成員型別是結構體本身;但是成員可以定義為該結構體的指標

  4. 結構體物件可以進行賦值運算,但不能進行算術、關係運算等

  5. 將結構體物件作為函式實參傳遞到函式中,採用值傳遞的方法;將結構體陣列和結構體指標作為函式引數,採用地址傳遞方式

10. 記憶體計算補齊原則:

資料對齊原則-記憶體按結構體成員的先後順序排列,當排到該成員變數時,其前面所有成員已經佔用的空間大小必須是該成員型別大小的整數倍,如果不夠,則前面的成員佔用的空間要補齊,使之成為當前成員型別的整數倍。假設是地址是從0開始,結構體中第一個成員型別char型佔一個位元組,則記憶體地址0-1,第二個成員從2開始,int型所佔記憶體4個位元組,根據原則b,第一個成員所佔記憶體補齊4的倍數,故第一個成員所佔記憶體:1 + 3 = 4; 第二個成員佔5-8. 第三個成員佔8個位元組,滿足原則b,不需要補齊,佔9-16. 第四個成員佔一個位元組,佔17. 故總記憶體為1 + 3 + 4 + 8 + 1 = 17個位元組,但根據原則a,總位元組數需是8的倍數,需將17補齊到24, 故此結構體總位元組數為:24位元組

  1. 結構體內什麼資料型別佔用記憶體最大,為n位元組,則採用n位元組對齊,例:

  2. 結構型別無法將自己的型別作為其成員的型別,因為自己的型別定義尚不完整,要在結束的大括號(})後才算定義完整

  3. 結構型別和其他基本型別或陣列型別類似的用法,可以定義在函式之中或函式之外

14. 關於在結構體中用指標和用變長結構體(a[0])的區別:

① 在位置方面:指標可以放在任何地方,但是變長結構體的變長部分一定要放在結構體的最後。

② 在記憶體佔用方面:指標會佔一個指標的大小的記憶體空間,但是變長陣列是不佔記憶體的,它只是一個佔位符。

③ 在記憶體佈局方面:指標指向的記憶體和結構體的記憶體可以是不連續的,但是變長部分和結構體的記憶體必須是連續。

④ 在記憶體釋放方面:使用指標,就要先釋放指標所指的記憶體再釋放整個結構體的記憶體,否則會照成記憶體洩露。

但是使用變長結構體直接釋放整個結構體的空間就可以了

⑤ 一個限制:指標可以用在C++的類中,但是變長結構體就不可以了。因為有些編譯器會將一些額外的資訊放在類的最後,比如vptr或者虛基類的內容,使用了變長的類,就會把這部分的值改變,這種行為是未定義的,誰也不知道會發生什麼

⑥ 故在結構體中定義變長陣列,會出現編譯器會認為這就是一個長度為0的陣列,而且會支援對於長陣列的越界訪問的情況

(二)共用體

  1. 共用體(聯合)是一種同一儲存區域由不同型別變數共享的資料型別;結構體是用同一個名字引用的相關變數的集合

  2. 共用體的大小取內部最大的位元組數

  3. union 是一種特殊的類, C與C++中都可以使用

  4. 定義格式:union 共用體型別名{成員列表};// 共用體型別名與union一起作為型別名稱

  5. 定義共用體物件時只能按一個成員給予初值

  6. 所有成員的值是相同的,區別是不同的型別決定了使用這個值的全部還是部分

(三)列舉

  1. 宣告列舉變數三種方法:

① enum 列舉型別名 {命名列舉量列表(例:列舉識別符號=整型常數)} 列舉物件名列表;

// 例:enum DIR {LEFT,UP} dir=LEFT;(dir為物件名)

② enum 列舉型別名 列舉物件名列表;

③ enum {命名列舉量列表} 列舉物件名列表;

  1. 列舉變數是全域性變數的情況下, 列舉值的預設值是0,不是列舉的第一個值。 其他情況,其值是不定的,而且不限定於所列出的列舉值;初始化的話就: {......}x=123;

  2. 命名列舉常量(大括號中的元素)是一個整形常量值,故是右值不是左值

  3. weekday = weekday(2) // 其中weekday是列舉型,需要用此C++形式的強制型別轉換才能賦值2

​ weekday = (weekday)2 // 此為C語言的強制型別轉換

  1. 列舉變數的大小,即列舉型別所佔記憶體的大小。由於列舉變數的賦值,一次只能存放列舉結構中的某個常數。所以列舉變數的大小,實質是常數所佔記憶體空間的大小(常數為int型別,當前主流的編譯器中一般是32位機器和64位機器中int型都是4個位元組)
  2. 列舉值預設從零開始並從先前的值開始向上計數
  3. 定義列舉型別的主要目的是:增加程式的可讀性
  4. 如果某個列舉符的值均為非負,該列舉的表示範圍就是[0:2k-1],2k是能使所有列舉符位於此範圍內的最小的2的冪;如果存在負的列舉符值,則該列舉的取值範圍就是[-2k:2k-1].這樣就定義了一個最小的位段,其中能儲存所有的列舉符值的常規2補碼錶示;例enum Number{one=1, two=2, four=4, eight=8};的取值範圍是 0~15