0

我正在尝试减少主要用 C++ 开发的应用程序的内存占用,而我正在研究的一件事是通过引用返回一个特别大的数据结构,而不是按值返回它们。我需要一些确认。例如,假设我在一个类some_object中有如下成员函数:

const some_type& get_some_type(...) {
   ...;
   return ...;
}

对比

const some_type get_some_type(...) {
   ...;
   return ...;
}

我的理解是否正确,通过调用后者(按值返回)进行分配会some_type在应用程序执行期间的某些点在内存中留下两个数据副本,而调用前者(按引用返回)可以避免这种情况?

作为减少内存占用的总体目标的一部分,另一项努力是以some_type排除使用上述按引用返回选项的方式更改定义的方式。在这种情况下,因为some_type(它实际上是一个容器,比如说,类型数据的容器data_type)在循环中使用,如下所示:

const some_type& = some_object->get_some_type(); // returns by ref. a large container
for(...) {
   ...;
   data_type = some_type.at(...);
   ...;
}

我假设如果我们被限制使用上面的按值返回,那么我需要通过引入一个新函数来按值获取容器的元素来进行如下更改get_some_type_at(这样做有什么缺点我应该是知道,比如说,在性能方面?):

for(...) {
   ...;
   data_type = some_object->get_some_type_at(...); // returns by value a small object
   ...;
}

同样,我主要是在寻找对这些方面的确认。但细节和见解是最受赞赏的。感谢您的时间和兴趣!

4

2 回答 2

3

Most good compilers implement return value optimisation, so you needn't worry about unnecessary construction of copy objects.

Hence, choose

some_type get_some_type(...) {
   ...;
   return ...;
}

unless you're using an old compiler.

(Acknowledgement to juanchopanza; also drop the const object return; explanation in comments.)

See http://en.wikipedia.org/wiki/Return_value_optimization for more details; pointless to duplicate this here.

于 2013-06-22T21:31:32.413 回答
2

我的理解是否正确,通过调用后者(按值返回)进行分配会在应用程序执行期间的某些点在内存中保留数据的两个副本 some_type ,而调用前者(按引用返回)避免了这种情况?

对于现代编译器,这种可能性非常小。该标准特别祝福所谓的返回值优化(和命名的返回值优化)让编译器避免在这种情况下创建额外的副本。我所知道的每一个相当现代的编译器都包含这种优化。在某些情况下(例如 gcc),即使您告诉编译器不要进行优化,它们也会执行此优化。启用优化后,您必须查看大约 10 年(可能更长时间)才能找到没有这样做的编译器。

C++11 增加了“移动”功能,可以做更多的事情来确保解决您关心的问题,即使您按值返回一个大对象。

底线:在我看来,你在错误的地方寻找什么——你可能想考虑向你的类添加一个显式的移动构造函数(可能还有移动赋值运算符),但一般来说,你可以按值返回并且要开心。

于 2013-06-22T21:34:43.660 回答