使用emplace_back添加std::pair对象时,如何避免临时变量的创建与销毁?
减少
std::vector<std::pair<A,A>>元素添加时的构造/析构操作 问题描述
我有一个存储std::pair类型元素的vector容器,发现添加元素时存在大量构造/析构操作。以下是演示代码及运行输出:
演示代码
#include <iostream> #include <vector> using namespace std; struct A { explicit A(int a) : a_(a) { printf("%d created at %p\n", a_, (void *)this); } A(const A &other) : a_(other.a_) { printf("%d copied\n", a_); } A(A &&other) : a_(other.a_) { printf("%d moved into %p\n", a_, (void *)this); } A &operator=(const A &other) { printf("%d copy assigned\n", a_); a_ = other.a_; return *this; } A &operator=(A &&other) { printf("%d move assigned to %p\n", a_, (void *)this); a_ = other.a_; return *this; } ~A() { printf("%d %p dead\n", a_, (void *)this); } int a_; void show() const { printf("%d\n", a_); } }; int main() { std::vector<std::pair<A, A>> v; v.emplace_back(std::make_pair(A(1), A(2))); while(1); }
编译运行命令
g++ a.cpp -O2 ./a.out
运行输出
2 created at 0x7fffb413ca84 1 created at 0x7fffb413ca80 1 moved into 0x7fffb413ca88 2 moved into 0x7fffb413ca8c 1 moved into 0x1cf72c0 2 moved into 0x1cf72c4 2 0x7fffb413ca8c dead 1 0x7fffb413ca88 dead 1 0x7fffb413ca80 dead 2 0x7fffb413ca84 dead
如输出所示,共产生了4个临时变量,请问如何减少这类操作?
解决方案
问题根源在于你先用std::make_pair(A(1), A(2))构造了一个临时std::pair对象,再通过emplace_back将这个临时pair移动到vector中——这会触发两次A的临时构造、一次pair的临时构造,以及多次移动操作。
要彻底消除临时变量,直接给emplace_back传递std::pair<A,A>构造所需的参数,让它在vector的存储空间原地构造pair和内部的A对象:
修改main函数中的调用代码:
int main() { std::vector<std::pair<A, A>> v; v.emplace_back(1, 2); // 直接传递构造A的参数,原地构造pair while(1); }
修改后的运行输出(示例)
1 created at 0x55f8a2c22c20 2 created at 0x55f8a2c22c24
可以看到,现在仅构造了两个A对象,完全没有临时变量和移动操作——因为emplace_back会完美转发参数,直接在vector分配的内存中构造std::pair<A,A>,而pair的两个A成员会直接用传入的1和2调用构造函数,全程无额外临时对象产生。
另外,如果vector后续会频繁添加元素,建议提前用reserve预分配足够内存,避免vector扩容时触发元素的移动/拷贝操作。
内容的提问来源于stack exchange,提问作者kevin h
相关产品推荐
相关产品推荐

