2

我正在考虑开发一些命名参数代码,但它让我想到了一些如下代码:

#include <utility>

int main() 
{
  using std::make_pair;
  auto x = make_pair(1, make_pair(2, make_pair(3, make_pair(4,5))));
}

现在,一个天真的实现会首先执行“make_pair(4,5)”,然后将结果复制到“make_pair(3, ...)”的第二个元素中,然后将其复制到“make_pair”的第二个元素中(2, ...)”等。

不幸的是,这将导致 O(n^2) 性能,并带有很多不必要的副本。我也看不出(命名的)返回值优化在这里有什么帮助。

理想情况下,make_pair(4,5) 意识到它将在 的最后一个位置x,并在那个位置构建自己。

更进一步:

#include <utility>

int main() 
{
  using std::make_pair;
  auto&& x1 = make_pair(3, make_pair(4,5));
  auto x2 = make_pair(1, make_pair(2, std::move(x1)));
}

我也想避免在这样的代码中复制。

这种优化是否如此明显以至于我应该假设编译器会执行它,或者是否有另一种方式我应该对其进行编码以避免复制?

4

2 回答 2

5

[N]RVO 在这种情况下确实有帮助。基本上发生的情况是分配了一个复合对象,并且每个函数的“返回值”最终直接进入将保存结果的对象。

如果你打算做很多这样的事情(尤其是在 C++11 中),那么使用元组几乎肯定会更清洁、更简单和更直接,所以你的:

auto x = make_pair(1, make_pair(2, make_pair(3, make_pair(4,5))));

最终会像:

auto x = make_tuple(1, 2, 3, 4, 5);

这可能不会对生成的代码产生太大影响,但是(至少在 IMO)它更容易阅读。

于 2011-05-02T06:06:15.040 回答
1
make_pair(1, make_pair(2, make_pair(3, make_pair(4,5))));

作为另一个 make_pair 的参数的所有 make_pairs 将创建一个临时值,该临时值被视为右值引用,因此不会被复制。

我认为您真正想要的是make_tuple

于 2011-05-02T06:08:05.000 回答