假设我有:
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
在两种情况下都包含哪些内容?
答案 0 :(得分:2)
首先,您永远不想返回对象的引用 在函数中动态分配。这是一个记忆 泄密等待发生。
除此之外,它取决于对象的语义,以及什么 你在干嘛使用参考(变体1)允许 修改它引用的对象,以便其他一些 函数将看到修改后的值。声明一个值 (变体2)表示您拥有自己的本地副本,以及任何副本 修改等将是它,而不是对象 在函数return中引用。
通常,如果函数返回对非const的引用,
这是因为它希望修改价值;一个典型的
例如std::vector<>::operator[]
,
表达式如下:
v[i] = 42;
期望修改向量中的元素。如果是这样的话 不的情况下,那么函数应该返回一个值,而不是 引用(你几乎不应该使用这样的函数) 初始化本地参考)。当然,这只会使 感觉如果你返回对可访问的东西的引用 别处;全局变量或(更可能)数据 由该职能所属的类所拥有。
答案 1 :(得分:1)
在第一个变体中,您将引用直接附加到动态分配的对象。这是拥有动态内存的一种相当非常规的方式(指针更适合于此目的),但它仍然为您提供了正确释放该对象的机会。即在你可以做的第一个main
结束时
delete &s;
在第二个变体中,您将丢失引用,即您丢失了指向该动态分配对象的唯一链接。该对象成为内存泄漏。
同样,通过引用拥有一个动态分配的对象并不会让我觉得这是一个好习惯。为此目的,通常最好使用指针或智能指针。出于这个原因,即使第一个变体可以正式兑换,你的两个变种都是有缺陷的。
答案 2 :(得分:0)
变体1将复制对象的地址并且将快速
变体2将复制整个对象并且速度很慢(如Variant2中已经指出的那样,你不能删除你通过调用new创建的对象)
用于编辑:两者都包含相同的对象
答案 3 :(得分:0)
您询问的两个选项都不是很好。在这种特殊情况下,如果使用较旧的C ++编译器,则应使用shared_ptr
或unique_ptr
或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
)
Variant 2.你在这里有泄漏,没有机会调用从你的函数返回的对象的析构函数。