构建复合对象时消除不必要的副本
我正在考虑开发一些命名参数代码,但这让我想到了一些如下代码:
#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 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
[N]RVO 在这种情况下确实有帮助。基本上发生的情况是分配一个复合对象,并且每个函数的“返回值”最终直接进入保存结果的对象。
如果你打算做很多这样的事情(特别是在 C++11 中),那么使用元组几乎肯定会更干净、更简单、更直接,所以你的:
最终会是这样的:
这可能不会影响生成的代码很多,但是(至少在我看来)它更容易阅读。
[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:
would end up like:
This probably won't affect the generated code much, but (at least IMO) it's a lot easier to read.
作为另一个 make_pair 参数的所有 make_pairs 将创建一个临时的,该临时的被视为右值引用,因此不会被复制。
我认为你真正想要的是make_tuple。
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.