复制构造函数

复制构造函数是一个特殊的构造函数,无论何时创建一个新对象,并且使用同一类的另一个对象对它进行初始化时,都会调用该构造函数。
关于复制构造函数的话题有很多。
实际上,这些特性用的好就叫特性,用不好就是缺陷了。
1.赋值
    属于同一类的对象赋值给另外一类对象。
    比如有一个类,名叫A,
    现在 A aa;
         A bb;
         aa = bb;
         这就是赋值,两个类都已经存在,且进行了初始化(这里是默认的),这样aa和bb的内容就是一样的,bb把自己的内容赋给了aa
         但是,如果是下面这样,就不是赋值了
         A aa;
         A bb = aa;
         这里就会调用复制构造函数。这里会有很多问题,比如深拷贝和浅拷贝。指针指向问题。所以需要深入了解复制构造函数。

2.2.默认复制构造函数
    如果没有显式的创建创建一个构造函数,那么编译器就会自动调用一个默认的复制构造函数。默认构造函数会按照成员赋值的方式,将现有对象的数据复制到新对象中。

#include <iostream>
#include<string>
using namespace std;

class Address{
	private:
		string street;
	public:
		//无参构造函数 
		Address(){street = " ";cout<<"无参"<<endl;}
		//有参构造 
		Address(string st){ street = st;cout<<"有参"<<endl;}
		//获取street 
		string getStreet() const {return street;}
};

int main(int argc, char** argv) {
	Address mary("beijing");
	//这里会调用复制构造函数 
	Address mike = mary; 
	//输出mike和mary此刻的地址 
	cout<<mike.getStreet()<<endl;
	cout<<mary.getStreet()<<endl;
	//改变mary的地址不会影响到mike的地址
	mary =Address( "shanghai");
	cout<<mike.getStreet()<<endl;
	cout<<mary.getStreet()<<endl;	
	return 0;
}

有参
beijing
beijing
有参
beijing
shanghai

3.默认构造函数的缺陷。
    比如存在指针的时候。直接复制给另一个对象,二者会同时指向一个地址,导致牵一发动全身
 

   #include <iostream>
#include<iomanip>
using namespace std;

class NumberArray{
    private:
        double* aPtr;
        int arraySize;
    public:
        NumberArray(int size,double value);
        
        
        void print() const;
        void setValue(double value);
};

NumberArray::NumberArray(int size,double value){
    arraySize = size;
    aPtr = new double [arraySize];
    setValue(value);
}

void NumberArray::setValue(double value){
    int index;
    for(index = 0;index < arraySize;index++)
        aPtr[index] = value;
}

void NumberArray::print() const{
    int index = 0;
    for(index = 0;index < arraySize;index++)
        cout<<aPtr[index]<<" ";
        cout<<endl;
}


int main(int argc, char** argv) {
    NumberArray first(3,10.5);
    
    NumberArray second = first;
    cout<<setprecision(2)<<fixed<<showpoint;
    first.print();
    second.print();
    //改变second的值,会发现first也跟着改变了。
    second.setValue(3.14);
    first.print();
    second.print();
    
    
    return 0;
}

这是做了一个double型的数组,用指针来管理这个数组。如果指向同一个空间,那么在后面用析构函数的时候,就可能造成内存泄漏,删除同一片空间,所以必须自己定义构造函数。

3.自定义一个复制构造函数
    类名(类名&)
    复制构造函数应该为新的对象分配新的空间。

#include <iostream>
#include<iomanip>
using namespace std;

class NumberArray{
	private:
		double* aPtr;
		int arraySize;
	public:
		NumberArray(int size,double value);
		NumberArray(const NumberArray&); 
		~NumberArray();
		void print() const;
		void setValue(double value);
};

NumberArray::NumberArray(int size,double value){
	arraySize = size;
	aPtr = new double [arraySize];
	setValue(value);
}

NumberArray::NumberArray(const NumberArray& obj){
	this->arraySize = obj.arraySize;
	this->aPtr = new double[this->arraySize];
	int index;
	for(index = 0;index < this->arraySize;index++)
		this->aPtr[index] = obj.aPtr[index];
	cout<<"copy\n"; 
}

NumberArray::~NumberArray(){
	if(this->arraySize > 0)
		delete [] this->aPtr;
}
void NumberArray::setValue(double value){
	int index;
	for(index = 0;index < arraySize;index++)
		aPtr[index] = value;
} 

void NumberArray::print() const{
	int index = 0;
	for(index = 0;index < arraySize;index++)
		cout<<aPtr[index]<<" ";
		cout<<endl;
}


int main(int argc, char** argv) {
	NumberArray first(3,10.5);
	
	NumberArray second = first;
	cout<<setprecision(2)<<fixed<<showpoint;
	cout<<"first:\n";
	first.print();
	cout<<"second:\n";
	second.print();
	 
	second.setValue(3.14);
	cout<<"first:\n";
	first.print();
	cout<<"second:\n";
	second.print();
	NumberArray third(3,1.1);
	cout<<"third:\n";
	third = first;//实际这里也会造成两次删除同一内存,需要重载运算符
	third.setValue(8.88);
	third.print();
	first.print();
	
	return 0;
}

4.复制构造函数被调用的情况。
函数如果是按值传递对象,就会调用复制构造函数
    (1)在同一个类中。用一个类去初始化另一个类。
    (2)函数的形参是类
    (3)函数返回值是类
    函数的形参和返回值是类的引用,则不会调用复制构造函数。
    这是因为这些调用产生一个临时对象的副本。

 

可以用上面的代码自己测试

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值