C++ 一道题搞定C++构造析构的调用

#include <iostream>
using namespace std;

class CSample 
{
    char ch1, ch2;
public:
    friend void set(CSample & s, char c1, char c2);
    CSample(char a, char b)
    {
        ch1 = a;
        ch2 = b;
        cout<<"CSample Constructor"<<endl;
    }
    CSample(const CSample & rhs)
    {
        ch1 = rhs.ch1;
        ch2 = rhs.ch2;
        cout<<"CSample Copy-constructor"<<endl;
    }
    CSample & operator = (const CSample & rhs)
    {
        ch1 = rhs.ch1;
        ch2 = rhs.ch2;
        cout<<"CSample Operator="<<endl;
        return *this;
    }
    ~CSample()
    {
        cout<<"ch1="<<ch1<<",ch2="<<ch2<<endl;
    }
};

void set(CSample & s, char c1, char c2)
{
    s.ch1 = c1;
    s.ch2 = c2;
}

CSample fun(CSample obj)
{
    set(obj, '7', '9');
    return obj;
}

int main()
{
    CSample obj1('7', '8');
    CSample obj2 = obj1;
    obj2 = fun(obj1);
    return 1;
}


这道题目的输入结果是:

CSample Constructor
CSample Copy-constructor
CSample Copy-constructor
CSample Copy-constructor
CSample Operator=
ch1=7,ch2=9
ch1=7,ch2=9
ch1=7,ch2=9
ch1=7,ch2=8

用的是g++编译的。

解释一下:

obj(‘7’,‘8’)这句话调用一般构造函数,输出CSample Contrucutor

第二句话,用obj1给obj2初始化,用一个已知的对方给另外一个对象初始化,调用拷贝构造函数,所以输出CSample Copy-constructor

调用fun(obj1)时,构造一个形参,所以调用拷贝构造函数,输出CSample Copy-constructor,此时obj1的值为(‘7’,8‘),而这个形参的值为(’7‘,’9‘),这里是按值传参数,所以对obj1没有改变,返回obj的时候,又构造一个临时对象,所以调用拷贝构造函数,输出CSample Copy-constructor,此时这个临时对象的值为(7,9),然后用这个临时对象给obj2赋值,调用重载函数,输出CSample Operator=,

然后反序调用析构函数,先析构临时对象,输出ch1=7,ch2=9;

再析构形参,输出ch1=7,ch2=9;

再析构obj2,输出ch1=7,ch2=9

再析构obj1,输出ch1=7,ch2=8

整个过程结束,要记住,一个对象作为实参进入一个函数时,只是自己拷贝一份进去,该函数结束时要把这份临时的复制对象析构掉,函数返回时返回一个对象也是先构造一个临时对象。



友元函数set并不是类的成员函数,记住。


总结一下构造和析构:

每个类至少有三个构造函数和一个析构函数。

三个构造函数为:普通构造函数,拷贝构造函数,operator=构造函数,如果没有申明构造函数,编译器会自动的生成默认构造函数,但是如果一旦出现了普通构造函数,编译器就不会自动生成默认构造函数。当用一个对象去初始化另外一个对象时,写成(obj) 或者 = obj,调用拷贝构造函数,没有拷贝构造函数,系统会自动生成一个默认的拷贝构造函数,当用一个对象给一个一个存在的对象赋值时,调用operator=构造函数,默认的构造函数,都是通过位拷贝进行复制的,所以,当出现指针的时候,调用默认的构造函数往往会出错。

构造派生类子对象的时候,先调用基类构造函数,按照继承的顺序,在调用子对象的构造函数,按照子对象声明的顺序,在调用自己的构造函数。这个顺序和初始化列表的顺序无关。

对于初始化列表,const成员只能在初始化列表里面进行初始化,static成员只能通过::进行初始化,不能那个写在构造函数里面。

一个对象作为形参的时候,其实是调用了一个默认拷贝构造函数构造了一个形参对象,对象作为返回值的时候也是如此,调用了默认的拷贝构造函数,

析构的顺序和构造的顺序完全相反;

析构函数只有一个,在对象生成周期结束的时候,编译器自动调用析构函数。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值