我不知道当我有这样的功能,会发生什么C++ 11会发生什么?当函数返回
'temp'在被销毁之前被拷贝到一个临时的r值(超出范围)并且C++ 11可能被NRVO优化(所以'temp'的拷贝被直接写入返回目的地插槽)?
我不知道当我有这样的功能,会发生什么C++ 11会发生什么?当函数返回
'temp'在被销毁之前被拷贝到一个临时的r值(超出范围)并且C++ 11可能被NRVO优化(所以'temp'的拷贝被直接写入返回目的地插槽)?
什么都应该被复制。有两种可能性:
temp
被移动到调用者范围内的对象;或者temp
成为调用者范围中对象的别名。这被称为“返回值优化”。在2011年之前(具体而言,没有移动语义),第一种情况需要复制而不是移动。第二种情况允许在C++ 98和11中使用。
在'std :: unordered_map
这通常会在没有任何特殊规则的情况下从temp
复制到函数的返回值。但是,标准中有两条规则旨在改善这一点。第一个是,该拷贝可以被省略(12.8/31):比
在与类返回类型的函数返回语句,当表达是一种非挥发性的自动对象的名称(其他一个功能或catch子句参数)用相同cvunqualified类型作为函数返回类型时,复制/移动操作可以通过直接构建自动物体插入函数的返回值
这通常称为命名被省略返回值优化(NRVO),return value optimization (RVO)的特例。
第二个问题是,由于这种情况下满足复制省略上述标准,它将首先被认为是移动(12.8/32):
当的复制操作的省音的标准是满足或将被满足,除了源对象是函数参数,并且要被复制的对象由左值指定的情况下,首先执行用于选择副本的构造函数的重载解析,就好像该对象由右值。
因此,编译器将尝试以下步骤:
注意的是,类必须有一张移动或拷贝构造函数这个工作,即使移动或复制会被省略。
NRVO意味着temp
本身是在返回值位置构造的。没有RVO,是的,temp
被复制/从堆栈中的位置移动到被销毁之前的返回值位置。
在没有RVO的C++ 11中,它应该被移动,而不是被复制。 –
复制最有可能通过C++ 03 *和* C++ 11中的NRVO消除。 – juanchopanza
它可能是:a)如果移动ctor可用,则移动;或b)如果第一个不起作用,则复制。当然,(N)RVO可以同时应用两次。 – Xeo
既然你不需要'b'的副本,第二个参数应该改成'const stringmap&b'。对于第一个,我建议将它移动到'temp',即'stringmap temp(std :: move(a));'。这不会破坏NRVO,所以返回值仍然是最优化的。 –