- 代码
- 对象返回
- 引用返回
- 总结
正确代码如下:(为了验证,我们自己加上了自定义析构函数和拷贝构造函数)
#define _CRT_SECURE_NO_WARNINGS 1 #include对象返回using namespace std; class Date { public: Date(int year = 0, int month = 1, int day = 1) { _year = year; _month = month; _day = day; } Date& operator=(const Date& d) { _year = d._year; _month = d._month; _day = d._day; return *this; } Date(const Date& d)//拷贝构造函数 { cout << "这是拷贝构造函数" << endl; } ~Date()//析构函数 { cout << "默认析构" << endl; } private: int _year; int _month; int _day; }; int main() { Date d1(2021, 10, 11); Date d2(2021, 11, 2); Date d3(2020, 12, 2); d1 = d2 = d2; return 0; }
传对象返回时回进行如下操作:
- 释放对象原来的堆资源
- 重新申请堆空间
- 拷贝源的值到对象的堆空间的值
- 创建临时对象,调用临时对象拷贝构造函数,将临时对象返回
- 临时对象结束,调用临时对象析构函数,释放临时对象堆内存
Date operator=(const Date d) { _year = d._year; _month = d._month; _day = d._day; return *this; }
引用返回如图最后三个析构函数是三个对象生命周期结束时调用的,而上面的三次拷贝构造和析构是因为传对象返回造成的
注意:
在这里可能看不到传对象返回的危害,但是当对于栈这种在堆上开辟空间的类来说会有两次释放同一空间的危害,报错
传引用返回:
- 释放对象原来的堆资源
- 重新申请堆空间
- 拷贝源的值到对象的堆空间的值
- 返回源对象的引用
Date& operator=(const Date& d) { _year = d._year; _month = d._month; _day = d._day; return *this; }
只有三次正常的析构函数调用
总结
如果赋值运算符返回的是对象引用,那么其不会调用类的拷贝构造函数,这是返回对象和返回引用的主要区别,返回引用的效率明显较高
更深入探讨请移步:C++本质:类的赋值运算符=的重载,以及深拷贝和浅拷贝



