浅谈区别该何时调动拷贝构造函数还是赋值语句
首先我们先看一段代码,在这个代码里面包括C++四少(构造函数 析构函数 拷贝构造函数 赋值语句)
#include<iostream>
using namespace std;
class Test
{
public:
Test (int d=0):data(d)
{
cout<<"create Test object:"<<this<<endl;
}
//Test t1(t)
//对象对对象一般为拷贝构造,则为对自身的引用,等同于对对象本身进行直接操作
Test(const Test &t)//有无const不是关键,主要是引用,等同于这块对对主函数对象t进行操作
{
cout<<"copy creat Test object:"<<this<<endl;
data=t.data;
}
//~t
//t2=t1//赋值语句
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;
};
void main()
{
Test t(10);
Test t1(t);//这块等价于 Test t=t1 用t对象初始化t1对象,则用到拷贝构造
Test t2;
t2=t1;//此时调动赋值语句 是拿对象给对象赋值
Test t3=t2//这块是拿对象初始化对象 调动拷贝构造,注意和上一条的区分
}
//区分到底是赋值还是初始的方式是:看等号左边的对象在这之前存在与否;
//若存在则为赋值,若不存在则为赋值;
拷贝构造函数的参数要采用引用。如果将一个真实的类对象作为参数传递到拷贝构造函数,则会引起无穷递归,程序无法编译
调动拷贝构造函数的时机 除了以上的初始化,还有另外俩种:
2-当函数的参数是对象参数:
void fun (Test x)
{
int value;
value=x.GetData();
}
//等同于先将t4把x初始化,再调动fun函数
void main()
{
fun(t4);//t4在调动fun函数之前先调用一次拷贝构造函数,在调用fun 函数
}
3-当函数的返回值是类对象,函数执行完成返回调用者时使用
(原因 :要建立一个临时对象,然后返回调用者)
Test fun (Test x)
{
int value;
value=x.GetData();
Test tmp(value);
return tmp;
}
本质是对象初始化对象时调用拷贝构造函数,因为在函数中局部对象在离开建立它的函数时就会自动被消亡,在处理这种情况时,编译系统会在调用函数的表达式中创建一个无名临时对象,该对象的生存周期只在函数调用处的表达式中。所谓的return对象,实际上是调用拷贝构造函数把该对象的值拷入临时对象。若返回的是变量,处理过程类似,只不过不调用构造函数。