【问题标题】:C++ Best way to return value?C++ 返回值的最佳方式?
【发布时间】:2020-09-03 01:48:19
【问题描述】:

我想知道一个比实际更理论的问题 - 从函数返回值的最佳方法是什么?我可以做这样的事情

std::string foo(void)
{
  std::string buf = "Hello World" + to_string(1);
  return buf;
}

或者我可以这样做

std::string bar(void)
{
  return "Hello World" + to_string(1);
}

我知道输出将是相同的,但是“更好”的方法是什么?还是编译器也一样?

【问题讨论】:

    标签: c++ function return


    【解决方案1】:

    这主要是风格问题。

    但由于copy elision,存在细微差别。

    由于 C++17 在返回纯右值(您的情况 return "Hello World" + to_string(1);)时,编译器必须执行复制省略,因为/返回值优化。在您使用return buf 的情况下,编译器可以进行复制省略/命名返回值优化,但它没有义务这样做。

    在 C++11 和 C++14 中,在可能但不是强制的情况下都复制省略。

    如果没有复制省略,您将拥有一个局部变量 buf 或一个局部临时变量 ("Hello World" + to_string(1)),它们将被复制到 return。使用复制省略将不会有本地对象。 buf 或临时将创建在调用者要存储对象的地方。

    这可能会导致类似于观察到的here 的影响,其中本地对象的地址与返回对象的地址相同(在调用方站点上)。

    因此,为了缩短临时性,您肯定会获得复制省略,从而获得更好的性能。使用buf,您可能会获得复制省略,但您也可能不会获得,因此性能会降低。与往常一样,如果性能至关重要,您应该对其进行衡量。如果这里的性能不重要,我会更喜欢你看起来更清晰的代码(或者可能更适合行长度限制)。

    【讨论】:

    • 也就是说,许多实现使用命名返回值优化 (NRVO) 已经很长时间了。虽然 NRVO 不是强制性的,但实际上这两个选项生成的代码在几乎所有现代实现中都是相同的。
    【解决方案2】:

    对于这两种情况,copy elision 可能会为 return 语句执行,复制/移动操作可能会被省略。

    对于第一种情况,

    在return语句中,当操作数是具有自动存储持续时间的非易失性对象的名称时,该对象不是函数参数或catch子句参数,并且属于同一类类型(忽略cv-资格)作为函数返回类型。这种复制省略的变体被称为 NRVO,“命名返回值优化”。

    对于第二种情况,

    在return语句中,当操作数是与函数返回类型相同的类类型(忽略cv-qualification)的prvalue时:

    从 C++17 开始,第二个是强制性的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-06-19
      • 1970-01-01
      • 2013-08-29
      • 2019-05-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多