c++中拷贝构造函数,浅拷贝和深拷贝的区别,以及移动构造函数总结

   一、构造函数、浅拷贝和深拷贝

在C++提供了一种特殊的构造函数,称为拷贝构造函数。拷贝构造函数具有一般构造函数的所有特性,其作用是使用一个已经存在的对象(由拷贝构造函数的参数指定的对象)去初始化一个新的同类对象,即完成本类对象的复制。程序员如果没有定义拷贝构造函数,系统会自动生成一个默认的拷贝构造函数,其功能是把已存在的每个数据成员都复制到新对象中。程序员定义拷贝构造函数时,一般形式:

  类名(类名 & 对象)

    {

    }

    拷贝构造函数在三种情况下会被自动调用

    (1)用一个对象去初始化一个同类的对象  XX B(A)

 (2) XX aa = a,当一个新对象被定义的时候,即便这个时候是使用了'='运算符,它真实调用的是初始化函数copy constructor,而不是调用copy assignment operator去进行赋值操作。;

    (3)如果函数的形参是对象,进行形参和实参结合时,调用拷贝构造函数。f(A);

    (4)如果函数的返回值是对象,返回主调函数时,调用拷贝构造函数。 XX B=g();

  其中默认的拷贝构造函数是浅拷贝。当类的数据成员有指针类型是,假设同类对象A初始化B,A和B对象使用同一内存区域。在撤销对象时,导致对这一内存的两次释放,也就是说浅层复制:只复制指向对象的指针,而不复制引用对象本身。这时候要求程序员编制拷贝构造函数,使对象B的指针指向另外的内存区域,这叫深拷贝,深层复制:复制引用对象本身。

   二、移动构造函数

   右值引用,临时值,如果是临时值,不调用深拷贝,而是移动构造函数(move construct),来提升性能。

#include<iostream>
using namespace std;
class Test{
public:
    Test() :x(0) 
    { 
        cout << "构造函数 this = " << this << endl; 
    }
    Test(int x) :x(x) 
    { 
        cout << "构造函数 this = " << this << endl;
    }
    Test(const Test& another) :x(another.x) 
    { 
        cout << "拷贝构造函数 this = " << this << " from " << &another << endl; 
    }
    Test(const Test&& another) : x(another.x)
    { 
        cout << "移动构造函数 this = " << this<< " from " << &another << endl; 
    }
    ~Test() 
    { 
        cout << "析构函数 this = " << this << endl; 
    }
    friend ostream& operator<<(ostream& out, const Test &t);
private:
    int x;
};

//运算符重载
ostream& operator<<(ostream& out, const Test &t){
    out << "&t = " << &t << ",x = " << t.x;
    return out;
}

Test maketest()
{
    Test x(4);
    cout << "hell" << endl;
    return x;
}
int main()
{
    //测试拷贝构造函数
    Test test(3);
    cout << test << endl;
    Test test2(test);
    cout << test2 << endl;
    cout << endl;
    //测试移动构造函数
    Test first = maketest();//有一个临时对象,
    cout << first << endl;
    cout << endl;
    system("pause");
}
    //测试移动构造函数1
    Test first = maketest();//有一个临时对象,
    /*
    测试1结果分析:正常情况下直接调用拷贝构造函数,如果定义了移动构造函数,
    则直接调用移动构造函数。
    */
    //测试移动构造函数2
    //Test first;//有一个临时对象,
    //first = maketest();
    /*
    测试2结果分析:正常情况下,是调用拷贝构造函数,然后调用赋值构造函数,
    但如果定义了移动构造函数,就是调用移动构造函数,然后调用赋值构造函数。
    */

 

输出结果:

 

 如果没有移动构造函数,可以看结果:

 用的拷贝构造函数,但拷贝构造函数有性能损失,可以参考

https://blog.csdn.net/weiqing00/article/details/80929788

 

posted @ 2016-12-08 13:00  月光下的脚步  阅读(1206)  评论(0编辑  收藏  举报