在C ++中通过引用返回 - 引用赋值与值赋值

时间:2013-11-14 10:00:40

标签: c++

假设我有:

    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在两种情况下都包含哪些内容?

4 个答案:

答案 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_ptrunique_ptrauto_ptr,并更改函数以使其返回指针,而不是引用。另一个好的选择是按值返回对象,特别是如果对象体积小且构造成本低。

通过值返回对象的修改:

SomeObject f() { return SomeObject(); }

SomeObject s(f());

简单,干净,安全 - 此处没有内存泄漏。

使用unique_ptr

SomeObject* f() { return new SomeObject(); }

unique_ptr<SomeObject> s(f());

此处使用unique_ptrshared_ptr的一个优点是,您可以在某个时刻更改函数f,以返回从SomeObject派生的类的对象并且不需要更改任何客户端代码 - 只需确保基类(SomeObject)具有虚拟构造函数。

为什么你考虑的选项不是很好:

变式1:

SomeObject& s = f();

你打算如何销毁这个物体?无论如何,您将需要对象的地址来调用它的析构函数,因此在某些时候您需要取消引用s引用的对象(&s

Variant 2.你在这里有泄漏,没有机会调用从你的函数返回的对象的析构函数。