引入:
class Stack { public: Stack(int capacity = 3) { _a = (int*)malloc(sizeof(int) * capacity); if (nullptr == _a) { perror("malloc"); exit(-1); } _top = 0; _capacity = capacity; } ~Stack() { free(_a); _top = _capacity = 0; _a = nullptr; } private: int* _a; int _top; int _capacity; }; void Func(Stack st) { //... } int main() { Stack st1; Func(st1); return 0; }
运行结果:
调用
Func
函数时创建临时Stack类对象st
,其中st._a
与st1._a
指向了同一块空间,这块空间在程序运行过程中会被销毁两次。
一、拷贝构造函数
1.1 概念
拷贝构造函数:只有单个形参——对本类类型对象的引用(一般用const修饰),在用已存在的类类型对象创建新对象时由编译器自动调用。
class Date { public: // ... // 拷贝构造函数 Date(const Date& d) { _year = d._year; _month = d._month; _day = d._day; } private: int _year; int _month; int _day; };
1.2 特性
- 拷贝构造函数是构造函数的一种重载形式。
- 拷贝构造函数只有单个形参且必须是类类型对象的引用,使用传值方式编译器会报错(引发无穷递归调用)。
- 若未显示定义,编译器会默认生成拷贝构造函数,默认生成的拷贝函数按内存存储、字节序完成拷贝,这种拷贝方式为浅拷贝(或值拷贝)。
内置类型的拷贝构造不需要我们自己实现了——类中没有涉及资源申请。
一旦涉及了资源申请,如:引入中的Stack类,则拷贝构造函数一定要写。
class Stack { public: // ... Stack(const Stack& st) { _a = (int*)malloc(sizeof(int) * st._capacity); if (_a == nullptr) { perror("malloc"); exit(-1); } memcpy(_a, st._a, sizeof(int) * st._top); _capacity = st._capacity; _top = st._top; } };
void Func(Date d) { // ... } int main() { Date d1; Func(d1); return 0; }
程序真实运行过程: