关于面试的问题---拷贝构造函数

1,为什么拷贝构造函数传入的必须是引用?

       如果拷贝构造函数中的参数不是一个引用,即形如CClass(const CClass c_class),那么就相当于采用了传值的方式(pass-by-value),而传值的方式会调用该类的拷贝构造函数,从而造成无穷递归地调用拷贝构造函数。因此拷贝构造函数的参数必须是一个引用。

       需要澄清的是,传指针其实也是传值,如果上面的拷贝构造函数写成CClass(const CClass* c_class),也是不行的。事实上,只有传引用不是传值外,其他所有的传递方式都是传值。
#include<iostream>
using namespace std;

class CExample
{
private:
	int m_nTest;

public:
	CExample(int x) : m_nTest(x)      //带参数构造函数
	{ 
		cout << "constructor with argument"<<endl;
	}

	// 拷贝构造函数,参数中的const不是严格必须的,但引用符号是必须的
	CExample(const CExample & ex)     //拷贝构造函数
	{
		m_nTest = ex.m_nTest;
		cout << "copy constructor"<<endl;
	}

	CExample& operator = (const CExample &ex)   //赋值函数(赋值运算符重载)
	{	
		cout << "assignment operator"<<endl;
		m_nTest = ex.m_nTest;
		return *this;
	}

	void myTestFunc(CExample ex)
	{
	}
};

int main(void)
{
	CExample aaa(2);  // 实例化对象,调用构造函数
	CExample bbb(3);  // 实例化对象,调用构造函数
	bbb = aaa;        // 赋值函数
	CExample ccc = aaa; // 拷贝构造函数,对象ccc不存在,通过对象aaa实例化,
	bbb.myTestFunc(aaa); // 拷贝构造函数 作为实参传入到一个函数

	return 0;	
}

结果

constructor with argument        // CExample aaa(2);
constructor with argument        // CExample bbb(3);
assignment operator              // bbb = aaa;
copy constructor                 // CExample ccc = aaa;
copy constructor                 //  bbb.myTestFunc(aaa);

横向拓展:

什么是拷贝构造函数?

构造函数是一种特殊的类成员函数,是当创建一个类的对象时,它被调用来对类的数据成员进行初始化和分配内存。(构造函数的命名必须和类名完全相同)

什么时候调用拷贝构造函数?

在C++中,3种对象需要复制,此时拷贝构造函数会被调用

1)一个对象以值传递的方式传入函数体

2)一个对象以值传递的方式从函数返回

3)一个对象需要通过另一个对象进行初始化

下面说说深拷贝与浅拷贝:

浅拷贝:如果复制的对象中引用了一个外部内容(例如分配在堆上的数据),那么在复制这个对象的时候,让新旧两个对象指向同一个外部内容,就是浅拷贝。(指针虽然复制了,但所指向的空间内容并没有复制,而是由两个对象共用,两个对象不独立,删除空间存在)

深拷贝:如果在复制这个对象的时候为新对象制作了外部对象的独立复制,就是深拷贝。

赋值函数

当一个类的对象向该类的另一个对象赋值时,就会用到该类的赋值函数。

当没有重载赋值函数(赋值运算符)时,通过默认赋值函数来进行赋值操作

A a;

A b;

b=a; 

强调:这里a,b对象是已经存在的,是用a 对象来赋值给b的!!


拷贝构造函数与赋值函数的区别

1)拷贝构造函数是一个对象初始化一块内存区域,这块内存就是新对象的内存区,而赋值函数是对于一个已经被初始化的对象来进行赋值操作。
2)一般来说在数据成员包含指针对象的时候,需要考虑两种不同的处理需求:一种是复制指针对象,另一种是引用指针对象。拷贝构造函数大多数情况下是复制,而赋值函数是引用对象
3)实现不一样。拷贝构造函数首先是一个构造函数,它调用时候是通过参数的对象初始化产生一个对象。赋值函数则是把一个新的对象赋值给一个原有的对象,所以如果原来的对象中有内存分配要先把内存释放掉,而且还要检察一下两个对象是不是同一个对象,如果是,不做任何操作,直接返回。



猜你喜欢

转载自blog.csdn.net/red_ear/article/details/79729113
今日推荐