既然C++具有const引用,为什么我要按值返回一些东西呢
Why should I ever return something by value, since C++ features const references?
考虑这个函数:
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
-语句之后另一个线程正在修改同一个对象,则通过引用返回变量可能会导致数据争用。
还是纯粹基于具体情况?
大多数情况下,您将按值返回,尤其是对于非成员函数。成员函数可能会返回对成员*的引用,但几乎没有非成员函数返回引用的情况。只有当你知道你需要(以及你在做什么)时,你才应该返回参考资料。
*如果真的需要,也只有。
如果返回非静态局部变量,则必须按值返回,因为当函数返回时,它将被销毁,从而使对它的任何引用都无效。在这种情况下,副本通常可以用移动来替换,或者完全删除。
如果你正在返回一些持久的东西,那么你是对的;通常最好返回一个引用,让调用者决定是否应该复制它。但可能还有其他原因,比如线程安全,即使在那时也更喜欢按值返回:通过返回副本,读取器无法访问持久对象,而另一个线程可能正在修改它。
- 莱克斯没有返回我想要的东西
- C ++程序如何返回我的数组或写入全局变量
- 为什么我要从串口读取垃圾?
- 保持排序的数据结构,允许log N插入时间,并且可以返回我在log N中查找的元素的索引
- 每次我要使用外部资源时,我都会得到:collect2。exe:错误 ld 返回 1 退出状态
- 乘法返回我的值不正确
- 单元测试类无法在我要测试的同一解决方案中的另一个项目中找到类
- 为什么我要尝试在一个if语句中调用两个fucntions,但是在第一个完成后它忽略了另一个功能?(C )
- 3-D平面过滤EVD Lansac ..我要去哪里
- 如何在 c++ 中返回我自己的结构
- 当我要修改指针到常量整数时,为什么我的编译器不显示错误
- 为什么我要获得元素填充元素的零长度
- 为什么我要获得不同的输出?我使用有界的缓冲区,pthreads和Semaphores对C 进行编码
- 当我要退出应用程序时,如何在QT中自动调用destructor
- getPeername()在客户端在虚拟机上运行时返回我的本地主机地址
- C 为什么我要获得此输出.(这里的绿角)
- 为什么我要获得此代码的匿名类型警告
- 函数不返回我想要的值
- 既然C++具有const引用,为什么我要按值返回一些东西呢
- 为什么Clang有时返回nullptr,有时返回我想要的