1. 拷贝构造函数
#include <iostream>
#include <list>
#include <vector>
#include <random>
using namespace std;
class Construct{
public:
Construct(){
std::cout<<"构造函数:Construct()"<<std::endl;
};
Construct(int data):m_data(data){
std::cout<<"构造函数:Construct(int &data)-->"<<m_data<<std::endl;
}
Construct(const Construct &cons):m_data(cons.m_data){
std::cout<<"拷贝构造函数: Construct(const Construct &cons)-->"<<m_data<<std::endl;
}
Construct & operator=(const Construct & cons){
m_data=cons.m_data;
std::cout<<"重载赋值运算符=:Construct & operator=(const Construct & cons)"<<std::endl;
return *this;
}
~Construct(){
std::cout<<"析构函数:~Construct()"<<endl;
}
private:
int m_data=0;
};
int main()
{
Construct a(50); //调用构造函数:Construct(int data);
Construct b(a); //调用拷贝构造函数:Construct(const Construct &cons);
Construct c=b; //调用拷贝构造函数:Construct(const Construct &cons)?原因如下:
//!构造函数的目的是给对象进行内存空间的分配,而新对象c还未分配内存空间,此时调用b对其赋值,则会
//! 调用拷贝构造函数,在分配空间的同时,进行拷贝数据;
c=a; //调用Construct & operator=,因为c在前面已经进行初始化并分配存储空间了,此时是对一个存在的
//对象进行赋值,会调用赋值重载函数;
Construct *d=nullptr; //!不会调用任何构造函数,因为d是一个指针,只是可以指向一个Construct对象;
Construct *e=new Construct; //!调用构造函数:Construct(int data);
return 0;
}
//-----------------------------------------------------------------------------------
构造函数:Construct(int &data)-->50
拷贝构造函数: Construct(const Construct &cons)-->50
拷贝构造函数: Construct(const Construct &cons)-->50
重载赋值运算符=:Construct & operator=(const Construct & cons)
构造函数:Construct()
析构函数:~Construct()
析构函数:~Construct()
析构函数:~Construct()
复制构造函数是只在对象实例化时才会被调用,也就是说,有新对象产生(分配存储空间),才会调用构造函数;
赋值运算符则在一个现存的对象被赋予新的值时被调用,并且它有返回值。
上例中:
Construct a(50);
Construct b(a);
Construct c=b;
a,b,c
是新产生的对象,在此之前并没有a,b,c
,此时需要调用构造函数分配内存空间与初始化;所以会调用构造函数,至于调用构造函数是默认构造函数Construct(int &data)/Construct();
还是拷贝构造函数取决于传递的参数(重载);
c=a;
而c=a
中,对象c
是一个已经存在的对象,其内存空间已经分配,所以不会调用拷贝构造函数
,而是采用赋值的方式进行赋值(重载=
);
2.总结
所以并不是: Construct b(a);
就调用拷贝构造函数
,而Construct c=b;
就调用赋值运算符
;而是根据赋值对象的属性进行调用,如果是一个新对象,此时就必须调用构造函数(默认构造函数/拷贝构造函数)进行内存空间分配以及初始化;
对于已经存在的对象(已经分配了内存空间)则会执行赋值运算
;