[英]Return by reference in C++ - Reference assignment vs value assignment
假设我有:
class SomeObject {
};
SomeObject& f() {
SomeObject *s = new SomeObject();
return *s;
}
// Variant 1
int main() {
SomeObject& s = f();
// Do something with s
}
// Variant 2
int main() {
SomeObject s = f();
// Do something with s
}
第一个变体和第二个变体之间有什么区别吗? 在任何情况下,我都会使用一个?
编辑:另一个问题,在两种情况下s
包含什么?
首先,您永远都不想返回对在函数中动态分配的对象的引用。 这是等待发生的内存泄漏。
除此之外,它还取决于对象的语义以及您在做什么。 使用引用(变量1)可以修改其引用的对象,以便其他功能可以看到修改后的值。 声明一个值(变量2)意味着您拥有自己的本地副本,并且将对其进行任何修改等,而不是对函数返回中引用的对象进行任何修改。
通常,如果函数返回对非const的引用,那是因为它希望修改该值。 一个典型的例子是类似std::vector<>::operator[]
的表达式,其中的表达式是:
v[i] = 42;
预期会修改向量中的元素。 如果不是这种情况,则该函数应返回一个值,而不是引用(并且您几乎永远不应使用此类函数来初始化本地引用)。 当然,只有返回对其他位置可访问内容的引用,这才有意义。 函数所属的类所拥有的全局变量或(更可能是)数据。
在第一个变体中,您将引用直接附加到动态分配的对象。 这是拥有动态内存的一种非常不合常规的方法(指针将更适合于该目的),但是它仍然为您提供了适当地重新分配该对象的机会。 即在您的第一个main
结束时,您可以执行
delete &s;
在第二个变体中,您将丢失引用,即,您将丢失指向该动态分配对象的唯一链接。 该对象成为内存泄漏。
同样,通过引用拥有动态分配的对象并不是一个好习惯。 为此通常最好使用指针或智能指针。 因此,即使第一个变体可以正式兑换,您的两个变体也存在缺陷。
变体1将复制对象的地址,并且速度很快
变体2将复制整个对象,并且速度很慢(如变体2中已指出的那样,您不能通过调用new来删除创建的对象)
编辑:两个f包含相同的Object
您询问的两个选项都不是很好。 在这种特殊情况下,应该使用shared_ptr
或unique_ptr
,如果使用的是较旧的C ++编译器,则应使用auto_ptr
,并更改函数以使其返回指针而不是引用。 另一个好的选择是按值返回对象,尤其是在对象很小且构造便宜的情况下。
修改以按值返回对象:
SomeObject f() { return SomeObject(); }
SomeObject s(f());
简单,干净,安全-这里没有内存泄漏。
使用unique_ptr
:
SomeObject* f() { return new SomeObject(); }
unique_ptr<SomeObject> s(f());
在此处使用unique_ptr
或shared_ptr
的优点之一是,您可以在某个时候更改函数f
以返回派生自SomeObject
的类的对象,并且无需更改任何客户端代码-只需确保基类( SomeObject
)具有虚拟构造函数。
为什么您考虑的选项不是很好:
变体1:
SomeObject& s = f();
您将如何销毁物体? 无论如何,您都将需要该对象的地址来调用它的析构函数,因此有时需要取消引用s
所指的对象( &s
)。
变体2。您在这里泄漏,没有机会调用从函数返回的对象的析构函数。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.