构建复合对象时消除不必要的副本

发布于 2024-11-04 16:06:33 字数 753 浏览 12 评论 0原文

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

#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)));
}

我也想避免像这样的代码副本。

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

I was thinking of developing some named parameter code, but it got me thinking of some code like the following:

#include <utility>

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

Now, a naive implementation of this would do "make_pair(4,5)" first, then copy the result into the second element of "make_pair(3, ...)", and then copy that into the second element of "make_pair(2, ...)" etc.

This would result in O(n^2) performance unfortunately, with a lot of unnecessary copies. I can't see how (named) return value optimization helps here either.

Ideally, make_pair(4,5) realizes it's going to be in the last spot of x, and constructs itself in that place.

Taking this further:

#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)));
}

I'd like to avoid the copies in code like this also.

Is this optimization so obvious that I should assume compilers perform it or is there another way I should be coding this to avoid the copies?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

挽手叙旧 2024-11-11 16:06:33

[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);

这可能不会影响生成的代码很多,但是(至少在我看来)它更容易阅读。

[N]RVO does help in cases like this. Basically what happens is that one composite object gets allocated, and the "return value" from each of the functions ends up going directly into the object that will hold the result.

If you're going to do much of this (especially in C++11), it's almost certainly cleaner, simpler and more direct to use a tuple instead, so your:

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

would end up like:

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

This probably won't affect the generated code much, but (at least IMO) it's a lot easier to read.

画骨成沙 2024-11-11 16:06:33
make_pair(1, make_pair(2, make_pair(3, make_pair(4,5))));

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

我认为你真正想要的是make_tuple

make_pair(1, make_pair(2, make_pair(3, make_pair(4,5))));

All the make_pairs which are arguments into another make_pair will create a temporary which is treated as an rvalue reference and is thus not copied.

I think what you really want is make_tuple.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文