【问题标题】:Compiler Optimization with return (std::stringstream ss).str()带返回的编译器优化 (std::stringstream ss).str()
【发布时间】:2016-02-02 12:48:12
【问题描述】:

以下函数接受一个字符串作为参数,并在经过一些处理后返回另一个。

  1. 假设编译器将执行移动优化是否足够公平,并且我不会在每次调用后复制字符串的内容?这个函数是否应该遵循copy elision [(N)RVO]?

  2. 作为一种做法,这样做是否可取?

std::string foo(std::string const& s)
{ // Perform sanity check on s
  // ...

  std::stringstream ss;
  // do something and store in ss
  // ...

  return ss.str();
}

因为,否则,我一般遵循通过引用返回字符串的做法。所以,可以说,我的函数签名是:

void foo (std::string const& inValue, std::string& outValue);

【问题讨论】:

  • 你不用担心,编译器会通过移动或删除来优化复制。
  • 如果你把s放在stringstream中,那么我很确定它会在输入时被复制,在输出时被复制。
  • 你可以写return std::move(ss).str(),以防你的实现优化了这种情况(不确定是否有)。
  • 可以理解return move();部分!但我无法理解您评论的后半部分“不确定是否有”

标签: c++ rvo nrvo


【解决方案1】:

ss.str() 将创建一个临时字符串。如果您将该字符串分配给一个新实例,例如

std::string bar = foo("something");

复制省略或移动语义将发挥作用。

现在,如果您已经创建了一个字符串并将其分配给foo 的返回值,那么移动分配将生效

std::string bar;
// do stuff
bar  = foo("something");

我更喜欢这种方法,因为它不需要你已经在哪里创建了一个对象

void foo (std::string const& inValue, std::string& outValue);

您是否会创建一个空字符串来将其传递给函数以进行填充。这意味着您有一个构造和一个赋值,而在第一个示例中您可以只有一个构造。

【讨论】:

  • 我错过了“呼叫站点”的详细信息!感谢您详细说明。
  • @bvraghav 没问题。很高兴为您提供帮助。
【解决方案2】:

根据this,返回值时会更加优化:

返回值优化 (RVO) 允许编译器通过让调用者和被调用者为两个“副本”使用相同的内存块来优化副本。

【讨论】:

    猜你喜欢
    • 2017-11-15
    • 1970-01-01
    • 2013-06-07
    • 2012-04-21
    • 2014-08-17
    • 2016-07-21
    • 1970-01-01
    • 2011-11-07
    • 2010-09-21
    相关资源
    最近更新 更多