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

前言

本文承接上文,主要介绍C++语法中的另一个极其重要的成员函数------拷贝构造函数

简要介绍

如果一个构造函数的第一个参数是自身类型的引用,且其余参数均有默认值,那么这个构造函数就是拷贝构造函数,拷贝构造的效果如下

scss 复制代码
int main()
{
	Date d1(2026, 2, 21);
	d1.Print();
	Func1(d1);
	Date d2(d1);
	d2.Print();
	return 0;
}

也就是能用已经初始化的d1初始化d2,这就是拷贝构造的效果

特点

  • 拷贝构造是构造函数重载
  • C++规定传值传参必须调用拷贝构造
  • 拷贝构造的第一个参数必须是类类型对象的引用 如果第一个参数不是引用,只是一个类类型对象,那么就会发生传值传参,调用拷贝构造,然后又会拷贝,因此必须是传引用传参,这样的话问题就迎刃而解了。
  • 如果不希望传进去的实参发生改变,那么可以加一个const从而保护实参
  • 编译器自动生成的拷贝构造函数会对内置类型进行浅拷贝(按字节一个一个拷贝),对于自定义成员会调用其拷贝构造
  • 如果一个类显示实现了析构函数并释放了资源,那么就必须显示写拷贝构造
ini 复制代码
typedef int STDataType;
class Stack
{
public:
	Stack(int n = 4)
	{
		_a = (STDataType*)malloc(sizeof(STDataType) * n);
		if (nullptr == _a)
		{
			perror("malloc申请空间失败");
			return;
		}
		_capacity = n;
		_top = 0;
	}

	// st2(st1)
	Stack(const Stack& st)
	{
		cout << "Stack(const Stack& st)" << endl;

		// 需要对_a指向资源创建同样大的资源再拷贝值
		_a = (STDataType*)malloc(sizeof(STDataType) * st._capacity);
		if (nullptr == _a)
		{
			perror("malloc申请空间失败!!!");
			return;
		}
		memcpy(_a, st._a, sizeof(STDataType) * st._top);
		_top = st._top;
		_capacity = st._capacity;
	}

	void Push(STDataType x)
	{
		if (_top == _capacity)
		{
			int newcapacity = _capacity * 2;
			STDataType* tmp = (STDataType*)realloc(_a, newcapacity *
				sizeof(STDataType));
			if (tmp == NULL)
			{
				perror("realloc fail");
				return;
			}
			_a = tmp;
			_capacity = newcapacity;
		}
		_a[_top++] = x;

	}
	~Stack()
	{
		cout << "~Stack()" << endl;
		free(_a);
		_a = nullptr;
		_top = _capacity = 0;
	}
private:
	STDataType* _a;
	size_t _capacity;
	size_t _top;
};

比如栈这个结构,如果不显示写拷贝构造,那么按照字节拷贝会将st1和st2指向同一块空间,析构的时候会对一块空间析构两次,造成程序崩溃,因此需要自己写。

  • 注意一个易错点:传值返回会产生一个临时对象从而调用拷贝构造,因此应该传引用返回来减少拷贝构造的调用,返回的是返回对象的引用,但是这是如果返回的是当前函数局部域的局部对象,函数结束后对象销毁,这时引用就变成一个野引用了,因此需要保证返回对象的生命周期,当然加一个static也可以
javascript 复制代码
Stack& func2()
{
	static Stack st;//不加static的话出了作用域st就不在了
	return st;
}
int main()
{
	Stack ret = func2();
	return 0;
}

结语

拷贝构造函数到此就介绍完了,希望读者关注下文

相关推荐
KuaCpp19 分钟前
C++进程(下)
c++
来一碗刘肉面1 小时前
C++中的引用语法
c++·算法
杜子不疼.1 小时前
【Qt初识】工程起步:项目创建、代码解读与对象树
数据库·c++·qt
知无不研2 小时前
算法:Fizz Buzz解题思路
c++·算法·leetcode
汉克老师2 小时前
GESP2026年6月认证C++八级( 第二部分判断题(1-10))精讲
c++·归并排序·dijkstra·二分·互斥·gesp8级·可重复组合
nianniannnn3 小时前
c++复习自存--流、异常处理、多线程与C++工程规范
开发语言·c++
知无不研4 小时前
缺省参数与缺省函数的区别
c++·语法
从零开始的代码生活_6 小时前
C++ 类和对象中篇:默认成员函数、拷贝控制与运算符重载
服务器·开发语言·c++
csdndenglu6 小时前
Easy3D:一个轻量级、易用、高效的C++库,用于处理和渲染3D数据,无复杂要求时可替代VTK
开发语言·c++·图形渲染·3d渲染
^yi7 小时前
【C++】String 类
开发语言·c++