在构建复合对象时消除不必要的副本
Eliminating unnecessary copies when building composite objects
我本来想开发一些命名参数代码,但它让我想到了一些代码,如下所示:
#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_par(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)));
}
我也希望避免像这样的代码中的副本。
这种优化是如此明显,以至于我应该假设编译器执行它,还是我应该用另一种方式对此进行编码以避免复制?
[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(它更容易阅读。
make_pair(1, make_pair(2, make_pair(3, make_pair(4,5))));
作为另一个make_pair的参数的所有make_pair将创建一个临时的,该临时被视为右值引用,因此不会被复制。
我想你真正想要的是让自己成为一对。
相关文章:
- 用callgrind追踪不必要的副本
- 不必要的C++代码最终会出现在我完成的程序中吗?
- 总和的不必要行为C++?
- C++:将初始化的对象传递给另一个类的构造函数;需要不必要的构造函数吗?
- 为什么 std::string s = "123" 当不涉及副本时被视为复制初始化?
- 在这种情况下,使用 string_view 是否会导致不必要的字符串复制?
- std::mutex::lock() 产生奇怪(和不必要的)ASM 代码
- 如何在插入排序中使用 replace() 使语句变得不必要
- C 包装器C++库周围没有不必要的头文件
- 编译器是否消除了不必要的原子?
- 在 c++ 中不必要的包含
- GCC为AVR上的简单ISR产生不必要的寄存器推送
- 在序列化过程中删除不必要的内存分配
- QTREEWIDGET子分类,停止下降指示器显示给定有不必要的DropIndicatorPosition
- 如何在不指定不必要的模板参数的情况下使用模板类的成员类型
- 构造向量时如何摆脱(一个)不必要的副本
- 处理对“vector_binary_operation”类中“表达式”的引用,而无需不必要的副本
- 在调用C++/STL算法时,可视化消除了不必要的副本
- 在构建复合对象时消除不必要的副本
- 在汇编代码中查找不必要的缓冲区副本