3

假设有一个返回 a 的方法std::set

std::set<string> MyClass::myMethod() const
{
   std::set<string> result;
   // ... some code to fill result ...
   return result;
}

在调用方,我们可以通过myMethod两种方式存储结果:

void MyClass::test()
{
const std::set<string>  s1 = myMethod();  // 1
const std::set<string>& s2 = myMethod();  // 2 (using reference)
// ... some code to use s1 or s2 ...
}

我的问题是:

  • 它们之间有什么区别吗?
  • 哪种方式更好更高效?
4

5 回答 5

4
const std::set<string>  s1 = myMethod();  // 1

的返回myMethod被复制到 s1 中。根据大小,这可能需要很长时间。

const std::set<string>& s2 = myMethod();  // 2 (using reference)

存储对返回的临时对象的引用myMethod。这比上述方法少了一个副本,所以它要快一点(假设没有优化)。

这是一个特殊情况功能,用于引用一个变量,否则该变量将不再存在;。仅当它是const&(在您的示例中为)或 Rvalue 引用时才有效 - &&(感谢@Kos)。

于 2012-12-17T09:27:20.023 回答
3

从理论上讲,第二个版本更好,因为它不需要额外的副本。

在实践中,RVO 可能会发挥作用,因此它们应该大致相同。

于 2012-12-17T09:26:36.233 回答
2

是的,这些是不同的:

  1. const std::set<string> s1 = myMethod(); // 1: 复制临时对象

  2. const std::set<string>& s2 = myMethod(); // 2 (using reference): 临时文件的生命周期被延长,它避免了一份副本

请参阅第 88 周的 Guru。请注意,编译器可以通过使其具有相同的效率来优化它。

于 2012-12-17T09:27:29.820 回答
2

在实践中不太可能有任何差异。我已经测试了以下内容g++ 4.7.2

#include <string>

extern std::string f();
extern void g(const std::string&, const std::string&);

int main() {
  std::string        x = f();
  const std::string& y = f();
  g(x, y);
}

它为两个调用生成相同的代码f()

LEHB0:
        call    __Z1fv
LEHE0:
        leaq    16(%rsp), %rdi
LEHB1:
        call    __Z1fv
LEHE1:
        leaq    16(%rsp), %rsi
于 2012-12-17T09:35:02.143 回答
1
  1. 第一个版本将创建std::set对象,并将其移动到这一行

    const std::set<string> s1 = myMethod();

  2. 这将延长std::set方法中创建的对象的生命周期:

    const std::set<string>& s2 = myMethod();

因此,在性能方面两者都在做同样的事情。

于 2012-12-17T09:27:48.993 回答