既然C++具有const引用,为什么我要按值返回一些东西呢

Why should I ever return something by value, since C++ features const references?

本文关键字:返回 我要 具有 C++ const 引用 为什么 既然      更新时间:2023-10-16

考虑这个函数:

Thing func(){
    return something;
}

每次调用此函数时,都会生成something的副本并将其传递给调用者。

我的问题是,为什么不这样做(每次我都想按值返回一些东西)?

const Thing& func(){
    return something;
}

这样,我们就不会在没有理由的情况下复制something。如果客户端只需要从something"读取",而不需要"写入",那么const引用就可以做到这一点。如果客户端确实需要一个副本,它可以简单地将常量引用分配给一个变量,例如:

Thing thing = func(); // the object is passed by const reference, and then copied.

那么,有没有理由简单地按价值回报呢?

顺便说一句,这并不是说我太关心优化,只是我看不出有理由简单地通过价值来回报。


后续问题:阅读答案,我明白每种方法都有利弊。是否存在违约?例如"默认按值返回"?还是纯粹基于具体情况?

因为如果您的对象(无论出于何种原因)是在被调用函数的堆栈上创建的,那么返回并使用对它的引用是未定义的行为。

通过按值返回,编译器有时可以优化返回,并且不存在危险的悬空引用。有了C++11和move语义,这就被提升到了一个新的水平。

说"通过引用而不是通过值返回总是更好的"是没有意义的,每种使用引用的情况都必须单独考虑。

那么,有没有理由简单地按价值回报呢?

是的。例如,如果您正在返回一个函数局部变量。

int compute(int a, int b)
{
    int result;
    // a lot of magic
    return result;
}

如果该函数返回对任何类型的result的引用,那么它将是一个悬空函数。

除此之外,类类型为"by value"的返回函数局部变量可以通过复制省略进行优化——优化的名称为NRVO。如果这种优化不适用,新引入的移动语义可能会(尽管你应该只依赖于复制省略,但它运行得很好)。在这种情况下,没有动机返回参考资料。

此外,如果您希望将事情保密,则不希望返回参考资料。为什么要在公共成员函数中返回对私有成员变量的const引用?它表示成员变量存在,调用站点不必知道这些信息。还要考虑线程安全性:如果return-语句之后另一个线程正在修改同一个对象,则通过引用返回变量可能会导致数据争用。


还是纯粹基于具体情况?

大多数情况下,您将按值返回,尤其是对于非成员函数。成员函数可能会返回对成员*的引用,但几乎没有非成员函数返回引用的情况。只有当你知道你需要(以及你在做什么)时,你才应该返回参考资料。

*如果真的需要,也只有

如果返回非静态局部变量,则必须按值返回,因为当函数返回时,它将被销毁,从而使对它的任何引用都无效。在这种情况下,副本通常可以用移动来替换,或者完全删除。

如果你正在返回一些持久的东西,那么你是对的;通常最好返回一个引用,让调用者决定是否应该复制它。但可能还有其他原因,比如线程安全,即使在那时也更喜欢按值返回:通过返回副本,读取器无法访问持久对象,而另一个线程可能正在修改它。