c++ 11函数返回时会发生什么

C++11 what happens when a function returns

本文关键字:什么 函数 返回 c++      更新时间:2023-10-16

我想知道当我有一个这样的函数时会发生什么:

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'的副本直接写入返回目标槽)?

不应该复制任何内容。有两种可能:

  • temp被移动到调用者作用域中的对象;或
  • 移动被省略,并且temp成为调用者作用域中对象的别名。这被称为"返回值优化"。

在2011年之前(特别是,没有移动语义),第一种情况需要复制而不是移动。第二种情况在c++ 98和c++ 11中是允许的。

NRVO表示temp本身是在返回值位置构造的。没有RVO,是的,temp在被销毁之前从堆栈上的位置复制/移动到返回值位置。

在没有任何特殊规则的情况下,这通常会导致从temp复制到函数的返回值。然而,标准中有两条规则旨在改善这一点。第一种是可以省略(12.8/31):

在具有类返回类型的函数的返回语句中,当表达式是与函数返回类型具有相同cvunqualified类型的非易失性自动对象(函数或catch子句参数除外)的名称时,可以通过将自动对象直接构造为函数的返回值

来省略复制/移动操作。

这通常被称为返回值优化(NRVO),是返回值优化(RVO)的一种特殊情况。

第二个是,由于这种情况符合上述复制省略的标准,因此首先将其视为移动(12.8/32):

如果满足或将满足省略复制操作的条件(除了源对象是函数形参,且要复制的对象由左值指定),则首先执行选择复制构造函数的重载解析,就像对象由右值指定一样。

编译器将尝试以下步骤:

    这个类有一个move构造函数吗?
    • 如果是,要么移动它,要么忽略移动。
    • 如果没有,类是否有复制构造函数?
      • 如果是,移动它或省略它。
      • 如果没有,我们不能复制或移动这个对象。

请注意,该类必须有移动或复制构造函数才能工作,即使省略了移动或复制。