[c++]构造函数之拷贝构造

1. 构造函数调用规则

  • 一般情况下,编译器至少给类添加3个成员函数:
    • 默认构造函数(无参,函数体为空)
    • 默认析构函数(无参,函数体为空)
    • 拷贝构造函数, 对属性进行值拷贝
#include <iostream>
using namespace std;

class Object {};

int main()
{
	//正确,调用编译器提供的默认构造函数
	Object obj_1;		
	//错误,No constructor could take the source type, or constructor overload resolution was ambiguous		
	Object obj_2(10);	
	//正确,调用编译器提供的默认拷贝构造函数		
	Object obj_3(obj_1);		

	system("pause");
	return 0;
}
  • 如果用户自定义了有参构造函数,编译器不再提供默认构造函数,但会提供拷贝构造函数。
#include <iostream>
using namespace std;

class Object 
{
public:
	Object(int) {
		cout << "calling the parametric constructor" << endl;
	}
};

int main()
{
	//错误, no appropriate default constructor available
	Object obj_1;					
	//正确, 调用自定义的有参构造函数
	Object obj_2(10);	
	//正确, 调用编译器提供的默认拷贝构造函数		
	Object obj_3(obj_2);		

	system("pause");
	return 0;
}
  • 如果用户自定义了拷贝构造函数,编译器不再提供其他构造函数。
#include <iostream>
using namespace std;

class Object 
{
public:
	Object(const Object& obj) {
		cout << "calling the self-define copy constructor" << endl;
	}
};

int main()
{
	//错误, no appropriate default constructor available
	Object obj_1;		
	//错误, Object::Object(const Object &)': cannot convert argument 1 from 'int' to 'const Object &		
	Object obj_2(10);			

	system("pause");
	return 0;
}

2. 拷贝构造函数调用时机

  • 使用一个已存在对象初始化一个新对象。
  • 值传递的方式给函数参数传值。
  • 值方式返回函数的局部对象。
#include <iostream>
using namespace std;

class Object
{
public:
	Object() {
		cout << "calling the default constructor" << endl;
	}
	Object(int) {
		cout << "calling the parametric constructor" << endl;
	}
	Object(const Object& obj) {
		cout << "calling the copy constructor" << endl;
	}
	~Object() {
		cout << "calling the destructor" << endl;
	}
};
void test01(Object obj) {
	return;
}
Object test02() {
	Object obj_4;						//calling the default constructor
	return obj_4;
}

int main()
{
	Object obj_1;						//calling the default constructor
	Object obj_2(10);					//calling the parametric constructor

	//使用一个已存在对象初始化一个新对象
	Object obj_3(obj_1);				//calling the copy constructor
	
	//值传递的方式给函数参数传值
	test01(obj_1);						//calling the copy constructor
	
	//值方式返回函数的局部对象
	Object obj_5 = test02();			//calling the copy constructor
	
	system("pause");
	return 0;
}

3. 深拷贝和浅拷贝

  • 浅拷贝:简单的赋值拷贝操作。
  • 浅拷贝带来的问题就是堆区的内存重复释放
  • 以下代码中,obj_1和obj_2中的m_b在内存中共用同一片内存地址,调用析构函数时会重复释放该堆区内存。
#include <iostream>
using namespace std;

class Object 
{
public:
	Object(int a, int b)	//有参构造函数
	{
		m_a = a;
		m_b = new int(b);
	}
	~Object()
	{
		if (m_b != NULL)	//手动释放堆区开辟的内存
		{
			delete m_b;
			m_b = NULL;
		}
	}
private:
	int m_a;
	int* m_b;
};

int main()
{
	Object obj_1(10, 20);				
	Object obj_2(obj_1);			

	system("pause");
	return 0;
}
  • 深拷贝:在堆区重新申请空间,进行拷贝操作。
#include <iostream>
using namespace std;

class Object 
{
public:
	Object(int a, int b)			//有参构造函数
	{
		m_a = a;
		m_b = new int(b);
	}
	Object(const Object& obj)	
	{
		m_a = obj.m_a;
		//m_b = obj.m_b;			//浅拷贝默认的实现方式
		m_b = new int(*obj.m_b);	//深拷贝重新在堆区开辟内存
	}


	~Object()
	{
		if (m_b != NULL)			//手动释放堆区开辟的内存
		{
			delete m_b;
			m_b = NULL;
		}
	}
private:
	int m_a;
	int* m_b;
};

void test()
{
	Object obj_1(10, 20);
	Object obj_2(obj_1);
}
int main()
{
	test();

	system("pause");
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
为了完善C++中的构造函数拷贝函数的定义,我们需要了解它们的作用和使用方法。 首先,构造函数是一种特殊的成员函数,用于创建和初始化类的对象。它在对象创建时自动调用,为对象的成员变量分配内存,并进行默认的初始化。构造函数的定义方式为在类中定义一个与类同名的函数,并在函数体中编写初始化代码。 构造函数可以有多个重载版本,根据传入的参数类型和数量可以选择不同的构造函数。如果没有定义任何构造函数,则会自动生成一个默认的构造函数。需要注意的是,如果自定义了构造函数,则不再生成默认的构造函数。 其次,拷贝函数是一种特殊的成员函数,用于复制一个对象的值到另一个对象中。拷贝函数的定义方式为在类中定义一个以类名为参数的函数,并在函数体中进行值的复制。 拷贝函数可以有两种形式:浅拷贝和深拷贝。浅拷贝仅仅是将源对象的指针或引用复制给目标对象,这样会导致两个对象共享同一块内存区域,造成潜在的问题。深拷贝则是创建一个新的对象,并复制源对象中的数据,从而得到完全独立的两个对象。 为了实现拷贝函数,可以在类定义中声明一个拷贝构造函数,并在函数体中进行值的复制。如果没有定义任何拷贝函数,则会自动生成一个默认的拷贝构造函数,进行浅拷贝操作。 总结起来,完善C++中的构造函数拷贝函数定义,需要在类定义中分别定义构造函数拷贝函数,并在函数体中编写相应的代码。通过合理使用构造函数拷贝函数,可以更好地创建和复制对象,提高代码的可读性和灵活性。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值