我想知道当我有这样的功能时会发生什么:
typedef std::unordered_map<std::string,std::string> stringmap;
stringmap merge (stringmap a,stringmap b)
{
stringmap temp(a); temp.insert(b.begin(),b.end()); return temp;
}
函数返回时会发生什么?
'temp'是否在被销毁之前被复制到临时r值(超出范围)并且C ++ 11可能被NRVO优化(因此'temp'的副本直接写入返回目标槽)?
答案 0 :(得分:7)
不应复制任何内容。有两种可能性:
temp
被移动到调用者范围内的对象;或temp
成为调用者范围内对象的别名。这被称为“返回值优化”。2011年之前(具体而言,没有移动语义),第一种情况需要复制而不是移动。第二种情况在C ++ 98和11中都被允许。
答案 1 :(得分:5)
NRVO意味着temp
本身是在返回值位置构建的。没有RVO,是的,temp
被复制/移动到堆栈上的位置,然后被销毁到返回值位置。
答案 2 :(得分:4)
这通常会在没有任何特殊规则的情况下导致从temp
复制到函数的返回值。但是,标准中有两条旨在改进这一规则的规则。首先是可以省略副本(12.8 / 31):
在具有类返回类型的函数的return语句中,当表达式是具有与函数返回类型相同的cvunqualified类型的非易失性自动对象(函数或catch子句参数除外)的名称时,通过将自动对象直接构造到函数的返回值
中,可以省略复制/移动操作
这通常被称为命名返回值优化(NRVO),return value optimization (RVO)的一个特例。
第二个是,由于这种情况符合上述复制标准的标准,它将首先被视为一个移动(12.8 / 32):
当满足或将满足复制操作的省略标准时,除了源对象是函数参数,并且要复制的对象由左值指定,重载决策以选择构造函数首先执行复制,就像对象是由右值指定一样。
因此编译器将尝试以下步骤:
请注意,即使删除了移动或复制,该类也必须具有移动或复制构造函数才能生效。