深入理解四大函数:构造函数、拷贝构造函数、赋值函数、析构函数。

测试1:

#include<iostream>
using namespace std;

class Test{
public:
    Test(int d = 0):data(d){
        cout<<"Create Test Object:"<<this<<endl;
    }
    Test(const Test &t){
        cout<<"Copy Create Test Object:"<<this<<endl;
        data = t.data;
    }
    Test& operator=(const Test &t){
        cout<<"Assign:"<<this<<"="<<&t<<endl;
        if(this != &t){
            data = t.data;
        }
        return *this;
    }
    ~Test(){
        cout<<"Free Test Object:"<<this<<endl;
    }
public:
    int GetData()const{
        return data;
    }
private:
    int data;
};

Test fun(Test x){
    int value = x.GetData();
    Test tmp;
}

int main(){
    Test t1(100);
    Test t2;
    t2 = fun(t1);
    return 0;
}

结果:

理解:

构造函数:创建t1对象,30。

构造函数:创建t2对象,2C。

拷贝构造函数:调用fun函数,因为fun函数的参数是以对象的形式进行使用的,所以调用拷贝构造函数,C4。

构造函数:创建临时的tmp对象,A4。

拷贝构造函数:最终返回tmp,借助一个临时的无名对象,24。

析构函数:先析构tmp对象,再析构x对象。

赋值函数:fun函数返回的无名对象24给t2赋值,t2是2C。

析构函数:析构掉无名对象,24。

析构函数:析构掉t2对象,2C。

析构函数:最后析构掉t1对象,30。

 

测试2:

#include<iostream>
using namespace std;

class Test{
public:
    Test(int d = 0):data(d){
        cout<<"Create Test Object:"<<this<<endl;
    }
    Test(const Test &t){
        cout<<"Copy Create Test Object:"<<this<<endl;
        data = t.data;
    }
    Test& operator=(const Test &t){
        cout<<"Assign:"<<this<<"="<<&t<<endl;
        if(this != &t){
            data = t.data;
        }
        return *this;
    }
    ~Test(){
        cout<<"Free Test Object:"<<this<<endl;
    }
public:
    int GetData()const{
        return data;
    }
private:
    int data;
};

/*
//测试1
Test fun(Test x){
    int value = x.GetData();
    Test tmp(value);
    return tmp;
}
*/

//测试2
Test fun(Test x){
    int value = x.GetData();
    return Test(value);  //创建无名临时对象的语法
}

int main(){
    Test t1(100);
    Test t2;
    t2 = fun(t1);
    return 0;
}

结果:

 

理解:

构造函数:创建t1对象,30。

构造函数:创建t2对象,2C。

拷贝构造函数:调用fun函数,因为fun函数的参数是以对象的形式进行使用的,所以调用拷贝构造函数,C4。

构造函数:创建无名临时对象,24。

析构函数:析构x对象,C4。

赋值函数:fun函数返回的无名对象24给t2赋值,t2是2C。

析构函数:析构掉无名对象,24。

析构函数:析构掉t2对象,2C。

析构函数:最后析构掉t1对象,30。

 

测试3:

#include<iostream>
using namespace std;

class Test{
public:
    Test(int d = 0):data(d){
        cout<<"Create Test Object:"<<this<<endl;
    }
    Test(const Test &t){
        cout<<"Copy Create Test Object:"<<this<<endl;
        data = t.data;
    }
    Test& operator=(const Test &t){
        cout<<"Assign:"<<this<<"="<<&t<<endl;
        if(this != &t){
            data = t.data;
        }
        return *this;
    }
    ~Test(){
        cout<<"Free Test Object:"<<this<<endl;
    }
public:
    int GetData()const{
        return data;
    }
private:
    int data;
};

/*
//测试1
Test fun(Test x){
    int value = x.GetData();
    Test tmp(value);
    return tmp;
}
*/

/*
//测试2
Test fun(Test x){
    int value = x.GetData();
    return Test(value);  //创建无名临时对象的语法
}
*/

//测试3
Test fun(Test &x){
    int value = x.GetData();
    return Test(value);  //创建无名临时对象的语法
}

int main(){
    Test t1(100);
    Test t2;
    t2 = fun(t1);
    return 0;
}

结果:

 

理解:

构造函数:创建t1对象,30。

构造函数:创建t2对象,2C。

用了引用,所以不调用拷贝构造函数。

构造函数:创建无名临时对象,28。

赋值函数:fun函数返回的无名对象28给t2赋值,t2是2C。

析构函数:析构掉无名对象,28。

析构函数:析构掉t2对象,2C。

析构函数:最后析构掉t1对象,30。

 

测试4:

#include<iostream>
using namespace std;

class Test{
public:
    Test(int d = 0):data(d){
        cout<<"Create Test Object:"<<this<<endl;
    }
    Test(const Test &t){
        cout<<"Copy Create Test Object:"<<this<<endl;
        data = t.data;
    }
    Test& operator=(const Test &t){
        cout<<"Assign:"<<this<<"="<<&t<<endl;
        if(this != &t){
            data = t.data;
        }
        return *this;
    }
    ~Test(){
        cout<<"Free Test Object:"<<this<<endl;
    }
public:
    int GetData()const{
        return data;
    }
private:
    int data;
};

/*
//测试1
Test fun(Test x){
    int value = x.GetData();
    Test tmp(value);
    return tmp;
}
*/

/*
//测试2
Test fun(Test x){
    int value = x.GetData();
    return Test(value);  //创建无名临时对象的语法
}
*/

/*
//测试3
Test fun(Test &x){
    int value = x.GetData();
    return Test(value);  //创建无名临时对象的语法
}
*/

//测试4
Test& fun(Test &x){
    int value = x.GetData();
    return Test(value);  //创建无名临时对象的语法
}

int main(){
    Test t1(100);
    Test t2;
    t2 = fun(t1);
    return 0;
}

结果:

 

理解:

构造函数:创建t1对象,30。

构造函数:创建t2对象,2C。

用了引用,所以不调用拷贝构造函数。

构造函数:创建无名临时对象,C4。

析构函数:紧接着析构无名临时对象,C4。

赋值函数:fun函数返回的无名对象C4给t2赋值,t2是2C。

析构函数:析构掉t2对象,2C。

析构函数:最后析构掉t1对象,30。

这种方法有一个很大的问题:就是不能起到赋值的作用。因为临时对象一创建就被析构了。但是如果把写的赋值语句注释掉,赋值就对了。自动执行内部的赋值函数。

 

测试5:

#include<iostream>
using namespace std;

class Test{
public:
    Test(int d = 0):data(d){
        cout<<"Create Test Object:"<<this<<endl;
    }
    Test(const Test &t){
        cout<<"Copy Create Test Object:"<<this<<endl;
        data = t.data;
    }
    Test& operator=(const Test &t){
        cout<<"Assign:"<<this<<"="<<&t<<endl;
        if(this != &t){
            data = t.data;
        }
        return *this;
    }
    ~Test(){
        cout<<"Free Test Object:"<<this<<endl;
    }
public:
    int GetData()const{
        return data;
    }
private:
    int data;
};

/*
//测试1
Test fun(Test x){
    int value = x.GetData();
    Test tmp(value);
    return tmp;
}
*/

/*
//测试2
Test fun(Test x){
    int value = x.GetData();
    return Test(value);  //创建无名临时对象的语法
}
*/

/*
//测试3
Test fun(Test &x){
    int value = x.GetData();
    return Test(value);  //创建无名临时对象的语法
}
*/

/*
//测试4
Test& fun(Test &x){
    int value = x.GetData();
    return Test(value);  //创建无名临时对象的语法
}

int main(){
    Test t1(100);
    Test t2;
    t2 = fun(t1);
    return 0;
}
*/

//测试5
Test fun(Test &x){
    int value = x.GetData();
    return Test(value);  //创建无名临时对象的语法
}

int main(){
    Test t1(100);
    Test t2 = fun(t1);  //直接初始化
    return 0;
}

结果:

 

理解:

构造函数:创建t1对象,30。

构造函数:创建的无名临时对象就是t2对象,2C。

析构函数:析构掉t2对象,2C。

析构函数:最后析构掉t1对象,30。

版权声明:本文为博主原创文章,如有错误,恳请大家在评论区指出,在下不胜感激~如要转载注明出处即可~