我认为这有点主观;我不确定意见是否一致(我见过许多返回引用的代码片段)。
根据对我刚才问的这个问题的评论,关于初始化引用,返回一个引用可能是邪恶的,因为(据我所知)它更容易错过删除它,这可能导致内存泄漏。
这让我很担心,因为我已经遵循了一些例子(除非是我想象的事情),并且在相当多的地方这样做了……我误解了吗?它邪恶吗?如果是的话,到底有多邪恶?
我觉得因为我的指针和引用的混合包,加上我是c++的新手,以及完全不知道什么时候用什么,我的应用程序一定是内存泄漏的地狱…
另外,我知道使用智能/共享指针被普遍认为是避免内存泄漏的最佳方法。
一般来说,返回引用是非常正常的,并且经常发生。
如果你的意思是:
int& getInt() {
int i;
return i; // DON'T DO THIS.
}
那是各种各样的邪恶。stack-allocated i会消失,你什么都没有提到。这也是恶的。
int& getInt() {
int* i = new int;
return *i; // DON'T DO THIS.
}
因为现在客户最终要做一些奇怪的事情:
int& myInt = getInt(); // note the &, we cannot lose this reference!
delete &myInt; // must delete...totally weird and evil
int oops = getInt();
delete &oops; // undefined behavior, we're wrongly deleting a copy, not the original
请注意,右值引用仍然只是引用,所以所有邪恶的应用程序都是一样的。
如果你想要分配一些超出函数范围的东西,使用智能指针(或者一般来说,一个容器):
std::unique_ptr<int> getInt() {
return std::make_unique<int>(0);
}
现在客户端存储了一个智能指针:
std::unique_ptr<int> x = getInt();
引用也可以用于访问你知道生命期在更高级别上保持打开的东西,例如:
struct immutableint {
immutableint(int i) : i_(i) {}
const int& get() const { return i_; }
private:
int i_;
};
在这里,我们知道返回对i_的引用是可以的,因为不管调用我们的是什么,它都管理着类实例的生命周期,所以i_至少会存在这么长时间。
当然,这并没有什么错:
int getInt() {
return 0;
}
如果生命期应该留给调用者,而你只是在计算值。
总结:如果对象的生命周期不会在调用后结束,则可以返回引用。
“回复推荐信是邪恶的,因为,
只是(据我所知)它造就了它
更容易忘记删除它”
不正确的。返回引用并不意味着所有权语义。也就是说,只是因为你这样做:
Value& v = thing->getTheValue();
...并不意味着你现在拥有由v引用的内存;
然而,这是可怕的代码:
int& getTheValue()
{
return *new int;
}
如果你这样做是因为“你不需要那个实例上的指针”,那么:1)如果你需要引用,就解除对指针的引用,2)你最终会需要指针,因为你必须用delete匹配new,你需要一个指针来调用delete。
返回引用通常用于c++中大型对象的操作符重载,因为返回值需要复制操作。(在操作符重载中,我们通常不使用指针作为返回值)
但是返回引用可能会导致内存分配问题。由于对结果的引用将作为对返回值的引用传递给函数,因此返回值不能是自动变量。
如果你想使用返回引用,你可以使用静态对象的缓冲区。
例如
const max_tmp=5;
Obj& get_tmp()
{
static int buf=0;
static Obj Buf[max_tmp];
if(buf==max_tmp) buf=0;
return Buf[buf++];
}
Obj& operator+(const Obj& o1, const Obj& o1)
{
Obj& res=get_tmp();
// +operation
return res;
}
通过这种方式,您可以安全地使用返回引用。
但你总是可以使用指针而不是引用在函数中返回值。