首页 > 解决方案 > 返回默认构造对象是否会阻止 NRVO?

问题描述

假设我有一个类似的功能:

using std::vector;

vector<int> build_vector(int n)
{
   if (some_condition(n)) return {};

   vector<int> out;

   for(int x : something())
   {
      out.push_back(x);
   }

   return out;
}

return {}函数开头的是否会阻止 NRVO?我很好奇,因为这似乎等同于以下内容:

using std::vector;

vector<int> nrvo_friendly_build_vector(int n)
{
   vector<int> out;

   if (some_condition(n)) return out;

   for(int x : something())
   {
      out.push_back(x);
   }

   return out;
}

但我不清楚在第一种情况下是否允许编译器执行 NRVO。

标签: c++nrvo

解决方案


来自https://en.cppreference.com/w/cpp/language/copy_elision

在以下情况下,编译器允许但不需要省略类对象的复制和移动(C++11 起)构造,即使复制/移动(C++11 起)构造函数和析构函数具有可观察的一面-效果。对象直接构建到存储中,否则它们将被复制/移动到。这是一种优化:即使它发生并且没有调用复制/移动(C++11 起)构造函数,它仍然必须存在且可访问(就好像根本没有发生优化一样),否则程序会出错-形成:

  • 在 return 语句中,当操作数是具有自动存储持续时间的非易失性对象的名称时,它不是函数参数或 catch 子句参数,并且属于相同的类类型(忽略 cv 限定)函数返回类型。这种复制省略的变体被称为 NRVO,“命名返回值优化”。

  • ...

提前返回没有限制,因此两个版本都是 NRVO 的候选版本。


推荐阅读