c++初级 之 拷贝构造函数

参考来自:http://www.cnblogs.com/BlueTzar/articles/1223313.html

类X的拷贝构造函数的形式为X(const X& x)。

当用一个已初始化过了的自定义类类型对象去初始化另一个新构造的对象的时候,拷贝构造函数就会被自动调用。也就是说,当类的对象需要拷贝时,拷贝构造函数将会被调用。以下情况都会调用拷贝构造函数:
一个对象以值传递的方式传入函数体
一个对象以值传递的方式从函数返回
一个对象需要通过另外一个对象进行初始化。

如果在类中没有显式地声明一个拷贝构造函数,那么,编译器将会自动生成一个默认的拷贝构造函数,该构造函数完成对象之间的位拷贝。位拷贝又称浅拷贝,后面将进行说明。

自定义拷贝构造函数是一种良好的编程风格,它可以阻止编译器形成默认的拷贝构造函数,提高源码效率。

浅拷贝和深拷贝

  在某些状况下,类内成员变量需要动态开辟堆内存,如果实行位拷贝,也就是把对象里的值完全复制给另一个对象,如A=B。这时,如果B中有一个成员变量指针已经申请了内存,那A中的那个成员变量也指向同一块内存。这就出现了问题:当B把内存释放了(如:析构),这时A内的指针就是野指针了,出现运行错误。

举例说明:

Array.h


//类Array两个成员,一个int,另一个是指向一个大小为int的数组的指针

class Array
{
public:
	//构造函数
	Array(int count = 1);

	//拷贝构造函数
	Array(const Array &arr);

	//数据封装函数
	void setCount(int _count);
	void setpArr();
	int getCount();
	int* getArr();

	//功能函数
	void print();

	//析构函数
	~Array();

private:
	int m_iCount;
	int * m_pArr;
};

Array.cpp


#include"Array.h"
#include<iostream>
using namespace std;

//构造函数
Array::Array(int count)
{
	m_iCount =  count;
	m_pArr = new int[m_iCount]; // 严格还要判断内存是否申请成功,但只是演示一下,就这样了
	for(int i = 0;i < m_iCount;i++){
		m_pArr[i] = i;
	}
	cout << "Array()" << endl;
}

//拷贝构造函数
Array::Array(const Array &arr)
{
	//浅拷贝(直接赋值)
	//m_iCount = arr.m_iCount;
	//m_pArr = arr.m_pArr;//浅拷贝,容易导致一块内存被释放后指针会成为野指针或者一块内存被释放两次!!!严重错误

	//深拷贝(一般是针对指针而言的,为了防止错误。意思是两个指针指向不同的地址(两块内存空间不同),但这两个地址里的内容一模一样)
	m_iCount = arr.m_iCount;
	m_pArr = new int[m_iCount]; 
	for(int i = 0;i < m_iCount;i++){
		m_pArr[i] = arr.m_pArr[i];
	}
	cout << "Array(const Array &arr)" << endl;
}

//数据封装函数
void Array::setCount(int _count)
{
	m_iCount = _count;
}

void Array::setpArr()
{
	delete []m_pArr;//先释放掉旧的内存
	m_pArr = new int[m_iCount]; //申请新的内存
	for(int i = 0;i < m_iCount;i++){
		m_pArr[i] = i;
	}
}

int Array::getCount()
{
	return m_iCount;
}

int* Array::getArr()
{
	return m_pArr;
}

//功能函数
void Array::print()
{
	for(int i = 0;i < m_iCount;i++){
		cout << m_pArr[i] << "  ";
	}
	cout << endl;
}

//析构函数
Array::~Array()
{
	delete []m_pArr;
	m_pArr = NULL;
	cout << "~Array()" << endl;
}

demo.cpp

#include<iostream>
#include<stdlib.h>
//#include<string>   //注意不要写成string.h
#include"Array.h"
using namespace std;

int main()
{
	Array arr1;
	Array arr2 = arr1;
	arr1.setCount(5);
	arr1.setpArr();
	Array arr3(arr1);


	cout << arr1.getCount() << "," << arr1.getArr() << endl;
	cout << arr2.getCount() << "," << arr2.getArr() << endl;
	cout << arr3.getCount() << "," << arr3.getArr() << endl;
	arr1.print();
	arr2.print();
	arr3.print();
	system("pause");
	return 0;
}
//总结就是,一旦有指针成员要进行拷贝,就要用深拷贝来防止一块内存多次释放的错误。

运行结果:






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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值