鉴于此函数和函数调用:
std::string GetString() {
std::stringstream sstr;
const auto str = sstr.str();
return str;
}
const auto returnedStr = GetString();
当我将str
声明为const?
答案 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