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

来源:互联网 发布:淘宝客服自动确认地址 编辑:程序博客网 时间:2024/06/06 16:30
#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成员只能通过::进行初始化,不能那个写在构造函数里面。

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

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

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

0 0