# include
# include
using namespace std;
class Test
{
public:
Test() //默认构造函数
{
cout<<"Default constructor runs"<
a = t.a;
this->name = t.name;
cout<<"Copy constructor runs"<
a = t.a + 1;
this->name = t.name;
return *this;
}
private:
int a;
string name;
};
Test& CopyByRef(int val, string na)
{
Test temp(val,na);
return temp;
}
Test CopyByParameter(const Test t)
{
return t;
}
Test CopyByVal(int val, string na)
{
Test temp(val,na);
return temp;
}
int main()
{
//Test m;
//m = Test(10,"m");
//Test n = Test(m);
//Test b(m);
//Test x = m;
Test m = CopyByVal(20,"n");
//Test h;
//h = CopyByVal(20,"n");
//Test y = CopyByParameter(m);
//Test p(10,"p");
//Test q = Test(10,"q");
//Test k;
//Test j = Test();
//Test& c = CopyByVal(30,"n");
}
总结:
拷贝构造函数调用的4情况:
①显式调用拷贝构造函数:
如Test n = Test(m);
Test b(m);
隐式调用:
②定义一个对象并初始化的时候调用
Test x = m;
③函数返回类型为类的对象
如 Test CopyByVal(int val, string na)
④函数形参类型为类的对象
如CopyByParameter(const Test t)
下列语句:
Test p = Test(10,"q");
本来应该是先生成一个Test类的临时对象,然后调用拷贝构造函数把对象值赋给p
但是编译器投机取巧,既然临时对象只是为了去初始化p,除此之外再没其他作用。
还不如先生成一个"临时对象",然后把这个"临时对象"的内存送给即将要定义的对象Test p算了。
所以其实不会调用拷贝构造函数,只是在对象p的内存空间中利用给定的实参生成一个对象,生成的这个对象就成了p。
所以Test p = Test(10,"q"); 与 Test p(10,"q"); 完全等价
同理Test k = Test(); 也不会调用拷贝构造函数
Test k; 与 Test k = Test(); 完全等价
同样地,
Test m = CopyByVal(20,"n");
由于CopyByVal(20,"n")返回一个Test类的对象,所以CopyByVal(20,"n")函数会触发拷贝构造函数生成一个临时对象
本来应该是CopyByVal(20,"n")返回的这个临时对象会再次调用拷贝构造函数去初始化对象m ,
但是编译器投机取巧,将这个临时对象的内存空间送给了即将要定义的对象m
即在对象m的内存空间中生成"临时对象",生成的这个"临时对象"自然就成了对象m
Test& m = CopyByVal(20,"n")也同理
而1、Test p;
2、p = CopyByVal(20,"n");
由于语句1已经定义了对象p,为p分配了内存空间,
所以语句2中CopyByVal(20,"n")生成的临时对象的内存空间没法再送给对象p,
所以生成的这个临时对象通过赋值运算符= 将对象值赋给p, 语句2结束后(遇到;时)临时对象就会销毁
拷贝构造函数调用的4情况:
①显式调用拷贝构造函数:
如Test n = Test(m);
Test b(m);
隐式调用:
②定义一个对象并初始化的时候调用
Test x = m;
③函数返回类型为类的对象
如 Test CopyByVal(int val, string na)
④函数形参类型为类的对象
如CopyByParameter(const Test t)
下列语句:
Test p = Test(10,"q");
本来应该是先生成一个Test类的临时对象,然后调用拷贝构造函数把对象值赋给p
但是编译器投机取巧,既然临时对象只是为了去初始化p,除此之外再没其他作用。
还不如先生成一个"临时对象",然后把这个"临时对象"的内存送给即将要定义的对象Test p算了。
所以其实不会调用拷贝构造函数,只是在对象p的内存空间中利用给定的实参生成一个对象,生成的这个对象就成了p。
所以Test p = Test(10,"q"); 与 Test p(10,"q"); 完全等价
同理Test k = Test(); 也不会调用拷贝构造函数
Test k; 与 Test k = Test(); 完全等价
同样地,
Test m = CopyByVal(20,"n");
由于CopyByVal(20,"n")返回一个Test类的对象,所以CopyByVal(20,"n")函数会触发拷贝构造函数生成一个临时对象
本来应该是CopyByVal(20,"n")返回的这个临时对象会再次调用拷贝构造函数去初始化对象m ,
但是编译器投机取巧,将这个临时对象的内存空间送给了即将要定义的对象m
即在对象m的内存空间中生成"临时对象",生成的这个"临时对象"自然就成了对象m
Test& m = CopyByVal(20,"n")也同理
而1、Test p;
2、p = CopyByVal(20,"n");
由于语句1已经定义了对象p,为p分配了内存空间,
所以语句2中CopyByVal(20,"n")生成的临时对象的内存空间没法再送给对象p,
所以生成的这个临时对象通过赋值运算符= 将对象值赋给p, 语句2结束后(遇到;时)临时对象就会销毁