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

本文详细解析了一道C++笔试题,涉及静态成员变量、构造与析构顺序及拷贝构造函数调用场景等内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这是一道外企的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操作,将导致这两个对象析构的时候,同一块堆空间被释放两次,进而出现错误。

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

 

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

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值