从函数返回一个const对象会阻止从外部移动构造吗?

时间:2014-09-11 10:02:52

标签: c++ move-semantics

鉴于此函数和函数调用:

std::string GetString() {
  std::stringstream sstr;
  const auto str = sstr.str();
  return str;
}

const auto returnedStr = GetString();

当我将str声明为const?

时,是否会省略move-construction

2 个答案:

答案 0 :(得分:14)

在您的情况下,returnedStr将从GetString()的返回值进行移动构造,但该返回值将从str (1)<复制构造/ SUP>。如果str不是const,则返回值将从中移动构建。

请注意,在这两种情况下,返回值优化仍然适用,因此编译器仍然可以直接在str的空间中构造返回值(甚至returnedStr本身),跳过一个或两个复制/移动结构。这是由C ++ 11 12.8 / 31:

授予的
  

当满足某些条件时,允许实现省略类的复制/移动构造   对象,即使对象的复制/移动构造函数和/或析构函数具有副作用。在这种情况下,   该实现将省略的复制/移动操作的源和目标视为两个不同的   引用相同对象的方式,以及对象的破坏发生在时间的晚期   当两个对象在没有优化的情况下被销毁的时候。这种复制/移动的省略   在以下情况下允许称为 copy elision,的操作(可以合并到   消除多份副本):

     
      
  • 在具有类返回类型的函数中的return语句中,当表达式是a的名称时   具有相同cv-unqualified的非易失性自动对象(函数或catch子句参数除外)   键入函数返回类型,可以通过构造省略复制/移动操作   自动对象直接进入函数的返回值

  •   
  • ...

  •   
  • 当复制/移动尚未绑定到引用(12.2)的临时类对象时   对于具有相同cv-unqualified类型的类对象,可以省略复制/移动操作   将临时对象直接构造到省略的复制/移动

  • 的目标中   

第一个要点包括返回值构造的省略,另一个要点包括将返回值移动到returnedStr。注意“相同的cv-unqualified”类型的要求,这意味着无论cv限定符如何,这都有效。


(1)请注意,如果我们讨论的是X以外的std::string类,那个提供移动构造函数的const X&&,那么实际上,返回值将是使用此构造函数构造的移动(无论它可能具有什么语义)。

答案 1 :(得分:6)

Angew的答案是对的,但谁能记住所有的语言律师规则?

为了帮助我记住,我更容易编写以下来自STL自己口中的规则。

  

15)不要将本地作为const [16]

返回      

$禁止移动语义

     

16)当按值返回本地时不要使用move   完全相同的类型[16]

     

如果你这样做,将不会使用$ NVRO。

     

17)不要通过Rvalue参考(&amp;&amp;)[16]

返回      

$除非你真的知道你在做什么。

注意:

[16]不要帮助编译器,2013年本土化,http://www.youtube.com/watch?v=AKtHxKJRwp4