返回值或修改引用传递的参数是否更快?

Arr*_*kis 9 c++ return-value-optimization

在我写的程序中,我必须在函数之间传递大型数据结构(图像).我需要在不同的操作系统上尽可能快地使用我的代码(因此,我无法分析所有测试用例).我经常有表格的代码......

void foo() {
  ImageType img = getCustomImage();
}

ImageType getCustomImage() {
  ImageType custom_img;
  //lots of code
  return custom_img;
}
Run Code Online (Sandbox Code Playgroud)

AFAIK,该行将ImageType img = getCustomImage();导致调用复制构造函数img,返回值为custom_img其参数.维基百科说,一些编译器甚至会再次执行此操作,作为初始临时变量!

我的问题:通过使用pass by reference而不是返回值来绕过这种开销(图像的复制构造函数是昂贵的)通常会更快吗?

void foo() {
  ImageType img;
  getCustomImage(img);
}

void getCustomImage(ImageType &img) {
  //code operating directly on img
}
Run Code Online (Sandbox Code Playgroud)

我被告知如果编译器支持返回值优化,那么应该没有区别.这是真的?我现在可以(在合理范围内)假设这一点,当速度很重要时,我应该如何构建我的程序

Dav*_*eas 13

您应该编写可维护的代码,在大多数情况下,编译器非常擅长为性能做正确的事情.如果你觉得事情进展缓慢,那么测量一下性能,找到瓶颈之后,试着弄清楚如何改进它.

你是对的,逻辑上代码触发不同的复制结构:从custom_img返回的临时,然后到img调用者代码中的对象,但事实是两个副本都将被省略.

按值返回default-construct + pass-by-reference的特定情况下,我知道实现的所有调用约定都通过让调用者分配内存并将隐藏指针传递给被调用者来返回值,这有效地实现了你会尝试做.所以从性能的角度来看,它们基本上是等价的.

我在过去的两篇博客文章中写过这篇文章(函数参数和返回值中的值语义):

编辑:我故意避免讨论编译器无法应用NRVO的情况,原因是任何f可以引用对象进行处理void f( T & out ) { /* code */ }的函数:可以简单地转换为NRVO对于编译器通过简单的转换实现按值返回:T f() { T out; /* code */ return out; }