您的位置:首页 > 其它

对象的构造、析构、拷贝构造

2011-04-21 10:28 176 查看
这是一道外企的C++笔试题,要求写出结果并分析:

#include <iostream.h>

class A

{

public:

static int num;

A() {cout<<num++;}

~A(){cout<<num--;}

};

int A::num=0;

class B: public A

{

public:

B(){cout<<num++;}

~B(){cout<<num--;}

A f(A a) {return a;}

};

int main()

{

A a;

B b;

b.f(b);

return 0;

}

输出结果是 0123210-1-2,下面对于每次输出给出分析:

0 在A a, 调用了A的构造函数,输出0(注意对num使用的是后减)

1 在B b, 先调用A的构造函数,输出1

2 在B b, 再调用B的构造函数,输出2

在b.f(b), 首先传参时,A temp_a = (A)b, 这里通过拷贝构造函数生成temp_a ,再将 temp_a 赋给 f中的a,也是通过拷贝构造

数, 所以这里没有输出,即没有构造函数的调用,大家不要认为生成对象都要经过构造函数。

3 f返回时, temp_a 析构,调用A的析构函数 输出3

2 f返回时, a析构,调用A的析构函数 输出2

在return a,虽然main中没有定义变量接收 f 的返回值,但是实际上 f 返回的时候生成了一个临时值,如temp_a

1 f返回后, 返回的temp_a 析构,调用A的析构函数 输出1

0 main返回 b析构,先调用B的析构函数, 输出0

-1 main返回 b析构,再调用A的析构函数, 输出-1

-2 main返回 a析构,调用A的析构函数, 输出-2

构造函数的调用顺序: 先基类的构造函数,后派生类的构造函数。

析构函数的调用顺序: 先派生类的析构函数,后基类的析构函数。

先构造的对象后析构,后构造的对象先析构。

拷贝构造函数被调用的三种情况:

1.程序中需要建立一个新的对象,并用另一个同类对象对它初始化的时候。 例如: A a; A a_1 = a;

2.当函数的参数为类的对象的时候。 例如 :

void f(A a){}

void main()

{

A a_1;

f(a_1);

}

3.当函数的返回值类型为类的对象的时候。 例如:

A f()

{

A a_1;

return a_1;

}

void main()

{

A a;

a = f();

}

当自己定义的类中没有定义拷贝构造函数的时候,系统在需要调用拷贝构造函数的时候自动调用默认的拷贝构造函数。

这时候需要注意一个问题:

当类的成员变量中有一个指针变量,而在生成类对象后,对象的这个指针变量指向了一块堆空间,这时候,如果使用这个对象去初始化一个新的对象的时候,调用了默认的拷贝构造函数。这样,两个对象的指针都指向了同一块对空间,如果类的析构函数里对这个指针进行了delete操作,将导致这两个对象析构的时候,同一块堆空间被释放两次,进而出现错误。

这其实就是传说中的对象的深拷贝和浅拷贝的问题,要解决这个问题,就要定义自己的拷贝构造函数,在复制对象中指向堆空间的指针的时候,申请新的堆空间,并进行内容的复制。

从今天开始我要做一个自由的人,喂马、劈柴,神游世界。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: