1. 程式人生 > 其它 >基礎知識點 | 1025_關於初始化,初始化列表和union類的常錯題

基礎知識點 | 1025_關於初始化,初始化列表和union類的常錯題

1.初始化時的問題


// 程式碼如下,問哪一句會出錯?
char* s="AAA";	//1
printf("%s",s);	//2
s[0]='B';	//3
printf("%s",s);	//4

  • 第三句處出錯,原因在於,初始化指標時所建立的字串常量被定義為只讀。如果試圖通過指標修改這個字串的值,程式就會出現未定義的行為。
  • 第一句處定義了一個指標s,指向一塊常量區"AAA"的地址,所以修改 *s 是不合法的;如果定義成了char s[] = "AAA",就可以修改了。


2.建構函式中的初始化列表


// 程式碼如下,輸出 B1 1&B2&B1 2&B2&C 3,要求填寫________ 
class B1 {
public:
    B1(int i) {
        cout << "B1" << " " << i << "&";
    }
};

class B2 {
public:
    B2() {
        cout << "B2" << "&";
    }
};

class C : public B1, public B2
{
public:
    C(int a, int b, int c) : ________ {
        indiv = c;
        cout << "C" << " " << indiv;
    }
private:
    B1 m1;
    B2 m2;
    int indiv;
};

int main() {
    C c(1, 2, 3);
    return 0;
}


首先分析類B1和B2的建構函式:

  1. B1有顯式的建構函式且有引數,因此構造B1時必須使用帶參形式 B1 ( i )
  2. B2有顯式的建構函式但是無引數,因此構造B2可以使用 B2 b2()B2 b2,兩者均呼叫顯示定義的建構函式;

其次分析類C:

  1. C有兩個基類B1、B2,因此首先需要執行B1和B2的建構函式;
  2. C有兩個成員物件m1,m2,因此需要分別執行B1和B2對這兩個物件進行初始化;

所以按順序執行以下建構函式B1 -> B2 -> B1 -> B2 -> C

觀察輸出結果B1 1&B2&B1 2&B2&C 3與前面結論相符;考慮輸出中的1和2 兩個引數值,所以帶參構造順序如下:

B1(1) -> B2() -> B1(2) -> B2() -> C(1,2,3)

最後結合以上兩點分析結果:

將B2的建構函式省略即可得到 B1(a), m1(b)



3.一直在錯的題

// 程式碼如下,X定義如下,問輸出是什麼
union X{
    int x;
    char y[4]; 
};
int main() {
    X a;
	a.x=0x11223344;
    cout << a.y[1];
    return 0;
}

  • union類中的型別共享一段記憶體
  • 根據機器的不同,記憶體的儲存方式分為 大端法 和小端法
  • 所以 a.y[1] 可能取到 0x22 或者 0x33