C++类和对象(五) 拷贝构造函数

1 概念

        在现实生活中,可能存在一个与你一样的自己,我们称其为双胞胎。那在创建对象时,可否创建一个与已存在对象一某一样的新对象呢?

C++类和对象(五) 拷贝构造函数_第1张图片

        那在创建对象时,可否创建一个与已存在对象一某一样的新对象呢?

         拷贝构造函数:只有单个形参,该形参是对本类类型对象的引用(一般常用const修饰),在用已存在的类类型对象创建新对象时由编译器自动调用。

        2 特征

        拷贝构造函数也是特殊的成员函数,其特征如下:

        1. 拷贝构造函数是构造函数的一个重载形式。

        2. 拷贝构造函数的参数只有一个必须是类类型对象的引用,使用传值方式编译器直接报错,因为会引发无穷递归调用。

C++类和对象(五) 拷贝构造函数_第2张图片

        为什么会出现错误呢,我们知道形参是实参的一份临时拷贝,当我们创建形参的时候,就要对实参进行拷贝,而编译器对于自定义类型调用其拷贝构造函数(对于内置类型,编译器会直接拷贝),因此当我们创建形参的时候就要调用拷贝构造,调用拷贝构造的时候就会创建形参 ...... ........因此形成无穷递归调用。

C++类和对象(五) 拷贝构造函数_第3张图片

3. 若未显式定义,编译器会生成默认的拷贝构造函数。 默认的拷贝构造函数对象按内存存储按
字节序完成拷贝,这种拷贝叫做浅拷贝,或者值拷贝。 

C++类和对象(五) 拷贝构造函数_第4张图片

注意:在编译器生成的默认拷贝构造函数中,内置类型是按照字节方式直接拷贝的,而自定
义类型是调用其拷贝构造函数完成拷贝的。

4. 编译器生成的默认拷贝构造函数已经可以完成字节序的值拷贝了,但是对于开辟内存的类我们还能这样吗?

typedef int DataType;
class Stack
{
public:
	Stack(size_t capacity = 10)
	{
		_array = (DataType*)malloc(capacity * sizeof(DataType));
		if (nullptr == _array)
		{
			perror("malloc申请空间失败");
			return;
		}

		_size = 0;
		_capacity = capacity;
	}

	void Push(const DataType& data)
	{
	// CheckCapacity();
	_array[_size] = data;
	_size++;
	}
	~Stack()
	{
	if (_array)
	{
		free(_array);
		_array = nullptr;
		_capacity = 0;
		_size = 0;
	}
	}
private:
	DataType* _array;
	size_t _size;
	size_t _capacity;
};

int main()
{
	Stack s1;
	s1.Push(1);
	s1.Push(2);
	s1.Push(3);
	s1.Push(4);
	Stack s2(s1);
	return 0;
}

        答案是:不能!!

        对于日期类的拷贝,没有指针可以浅拷贝(按照字节进行拷贝)。但是对于有指针的类,我们浅拷贝的话,就会造成两个指针指向同一空间,在运行过程会对同一块内存多次初始化和销毁。

C++类和对象(五) 拷贝构造函数_第5张图片

C++类和对象(五) 拷贝构造函数_第6张图片

注意:类中如果没有涉及资源申请时,拷贝构造函数是否写都可以;一旦涉及到资源申请
时,则拷贝构造函数是一定要写的,否则就是浅拷贝。

5. 拷贝构造函数典型调用场景:

        使用已存在对象创建新对象
        函数参数类型为类类型对象
        函数返回值类型为类类型对象

C++类和对象(五) 拷贝构造函数_第7张图片

C++类和对象(五) 拷贝构造函数_第8张图片

        为了提高程序效率,一般对象传参时,尽量使用引用类型,返回时根据实际场景,能用引用
尽量使用引用。

你可能感兴趣的:(c++,c++,开发语言)