浅谈区别该何时调动拷贝构造函数还是赋值语句?(以及调用拷贝构造函数的时机)

浅谈区别该何时调动拷贝构造函数还是赋值语句
首先我们先看一段代码,在这个代码里面包括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对象,实际上是调用拷贝构造函数把该对象的值拷入临时对象。若返回的是变量,处理过程类似,只不过不调用构造函数。

猜你喜欢

转载自blog.csdn.net/weixin_41747893/article/details/87932427