《Effective C++》条款21:不要返回reference,实在不行返回object
本章主要针对于返回引用做了一些相关的解释,并且涉及到了heap和stack空间的相关概念;
注意一下堆和栈的相关概念:
相当于C++来说,栈空间相当于显式直接声明,不用定义,回收由编译器负责,典型的回收情况是出了作用域自动销毁;
而堆空间则是通过new/delete来进行分配和回收,并且值得注意的是必须要进行delete操作,否则会造成内存溢出;
https://blog.csdn.net/qq_34175893/article/details/83502412
所以针对于返回引用,往往涉及两种情况,也就是栈空间和堆空间情况下;
书中给出的例子是const引用下的operator*函数,研究返回引用的关系;
由于传入的是const引用,所以必须想要返回的值必定在operator*函数体内构建;
针对于stack空间:
这就涉及到了典型的出了作用域直接销毁的情况;
class rational {
public:
rational(int a, int b) :n(a), d(b) {};
friend const rational& operator*(const rational& lhs, const rational& rhs) {
rational result(lhs.n * rhs.n, lhs.d * rhs.d);
return result;
}
private:
int n, d;
};
考虑上述情况,可以看到通过stack空间定义一个result,并且返回;
但是返回的引用必定是空的:函数结束后会消除局部local变量result,所以返回的是一个空的引用;
针对于heap空间:
class rational {
public:
rational(int a, int b) :n(a), d(b) {};
friend const rational& operator*(const rational& lhs, const rational& rhs) {
rational* result=new rational(lhs.n * rhs.n, lhs.d * rhs.d);
return *result;
}
private:
int n, d;
};
上述给出了一个使用new-heap返回的例子,但是问题是无法找准时间去delete返回的heap对象;
例如:当出现:a*b*c连乘的时候,必定会出现内存泄漏,因为无法获得b*c的指针,从而无法进行delete释放;
如果采用static形式进行返回:
class rational {
public:
rational(int a, int b) :n(a), d(b) {};
friend rational& operator*(const rational& lhs, const rational& rhs) {
static rational result(lhs.n * rhs.n, lhs.d * rhs.d);
return result;
}
private:
int n, d;
};
存在的问题是如果有一下判定形式if((a*b)==(c*d)),会导致恒等情况;
原因是,他们所使用的判定static对象相同;
如果硬要返回对象,直接采用object返回,以构造和析构函数的开销换取方便:
class rational {
public:
rational(int a, int b) :n(a), d(b) {};
friend rational operator*(const rational& lhs, const rational& rhs) {
return rational(lhs.n * rhs.n, lhs.d * rhs.d);;
}
private:
int n, d;
};
相当于用时间换方便,但是当对象太大的时候可能会造成开销过大;

浙公网安备 33010602011771号