基础知识点 | 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

posted @ 2021-10-25 16:15  不是勇士  阅读(110)  评论(0)    收藏  举报