C++-成员对象的构造函数的调用问题?

C++-成员对象的构造函数的调用问题?

想挽留 发布于 2017-05-03 字数 910 浏览 1228 回复 4

很多C++书籍都说,如果一个类中,我没有自定义任何构造函数,编译器会根据需要合成一个默认构造函数,但是,当我们自定义了构造函数之后,编译器就不会再合成构造函数了。
但是看看如下的代码:

 class AA
{
public:
AA():n(10){cout << "AA" << endl;}
private:
int n;
};

class BB
{
public:
BB():d(2.0){cout << "BB" << endl;}
private:
double d;
};

class CC
{
public:
CC():k(20){cout << "CC" << endl;}
void print()
{
cout << "i = " << i << endl;
cout << "k = " << k << endl;
}

private:
AA aa;
BB bb;
int i;
double k;
};

int main()
{
CC c;
c.print();
return 0;
}

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

清晨说ぺ晚安 2017-09-11 4 楼

系统分配内置类型的变量的时候,只是简单的在内存中开一块区域,然后把地址给你。而这段内存你永远不知道是什么数值。系统内存是虽然看上去每个程序都是独立的,但这是映射过的假象,在底层,所有的程序都调用的是同一个内存。无数个程序在你用这个内存之间就或读或写过这段内存了,所以,可以说初始值是随机的。
在VC的Debug状态,任何分配的内存都会被赋为0xCC这个样子,这是为了方便调试。一但到了Release,这些操作就没有了。

瑾兮 2017-08-25 3 楼

问题1:
不会合成构造函数,但是会填充构造函数的内容。具体可以参考深入理解C++对象模型。具体哪一章不太记得了。应该是在构造的语义那一章。里面讲了什么时候会很成构造函数,什么时候会填充构造函数,以及会向构造函数里面填充什么内容。我个人理解的一句话就是,当用户给出的构造函数满足不了编译器要做的事情的需求的时候,就会进行填充。例如初始化之类的操作。
问题2:
在debug下面,如果没有对变量进行初始化,变量就会被填充为0xcccccccc。全局变量和静态变量除外。填充成这个主要是用来执行运行时检查的,这部分内容具体可以参考windows核心编程第五版2.5.1节,里面也对这个内容做了很详细的描述了。
其中的文字描述,截个图来说明一下

在release下,参考了网上的资料,如果未初始化的变量,其值是随机的,是不确定的,也就是说是不可依赖的。
标准中说是未定义的,此处值的随机性有两个方面:new出来的结果和在栈中对象的值是不一样的;其他平台(例如编译器不同)不会有这个结果。

甜柠檬 2017-07-24 2 楼

下面这句代码

AA aa;

会去尝试调用一个构造函数:如果程序中没有定义构造函数,那么调用默认构造函数;如果程序中定义了一个不含参数的构造函数,那么会调用这个构造函数,否则找不到不含参数的构造函数就会报错。我将代码修改如下:

#include <iostream>

using namespace std;

class AA
{
public:
AA(int val):n(10){cout << "AA" << endl;}
private:
int n;
};

class BB
{
public:
BB():d(2.0){cout << "BB" << endl;}
private:
double d;
};

class CC
{
public:
CC():k(20){cout << "CC" << endl;}
void print()
{
cout << "i = " << i << endl;
cout << "k = " << k << endl;
}

private:
AA aa;
BB bb;
int i;
double k;
};

int main()
{
CC c;
c.print();
return 0;
}

Codeblocks 1.05 (GCC)编译报错,错误信息如下:

-------------- Build: Debug in test3 ---------------

Compiling: main.cpp
G:WorkspaceExerciseCodeBlockstest3main.cpp: In constructor 'CC::CC()':
G:WorkspaceExerciseCodeBlockstest3main.cpp:24:15: error: no matching function for call to 'AA::AA()'
G:WorkspaceExerciseCodeBlockstest3main.cpp:24:15: note: candidates are:
G:WorkspaceExerciseCodeBlockstest3main.cpp:8:6: note: AA::AA(int)
G:WorkspaceExerciseCodeBlockstest3main.cpp:8:6: note: candidate expects 1 argument, 0 provided
G:WorkspaceExerciseCodeBlockstest3main.cpp:5:8: note: AA::AA(const AA&)
G:WorkspaceExerciseCodeBlockstest3main.cpp:5:8: note: candidate expects 1 argument, 0 provided
Process terminated with status 1 (0 minutes, 0 seconds)
6 errors, 0 warnings

而且根据输出也明显看出是调用了程序中定义了无参数的构造函数。

再看下面一段代码:

#include <iostream>

using namespace std;

class AA
{
public:
AA():n(10){cout << "AA constructor (no parameter)" << endl;}
AA(int val):n(val){cout << "AA constructor (one parameter)" << endl;}
private:
int n;
};

class BB
{
public:
BB():d(2.0){cout << "BB" << endl;}
private:
double d;
};

class CC
{
public:
CC():k(20){cout << "CC" << endl;}
void print()
{
cout << "i = " << i << endl;
cout << "k = " << k << endl;
}

private:
AA *pAA;//不许调用构造函数
AA aa;//调用无参数的构造函数

BB bb;//调用无参数的构造函数
int i;
double k;
};

int main()
{
CC c;
c.print();
AA aa2(10);//调用有一个参数的构造函数
return 0;
}

运行结果如下:

灵芸 2017-05-28 1 楼

问题1:声明AA、BB对象时编译器会调用它的构造函数,可以这么理解,每个类有个一个默认构造函数AA(),如果你重新定义了构造函数,那么它就会被覆盖。你的例子中,无论是否重写CC的构造函数都会调用AA、BB的构造函数。覆盖的规则只作用于它所在的类,与类中类无关。

问题2:release中的值是不确定的,这个不确定的值其实受到当时堆栈情况影响,因此可能多次输出0。