深入理解C++11(十五)

深入理解C++11(十五)

emplace_back减少内存拷贝和移动
emplace_back能就地通过参数构造对象,不需要拷贝或者移动内存,相比push_back能更好地避免内存的拷贝与移动,使容器插入元素的性能得到进一步提升。在大多数情况下应该优先使用emplace_back来代替push_back。所有的标准库容器(array除外,因为它的长度不可改变,不能插入元素)都增加了类似的方法:emplace、emplace_hint、emplace_front、emplace_after和emplace_back,关于它们的具体用法可以参考cppreference.com。这里仅列举典型的示例。
vector的emplace_back的基本用法如下:

#include <vector>
#include <iostream>
using namespace std;
struct A
{
int x;
double y;
A(int a, double b):x(a),y(b){}
};
int main() {
vector<A> v;
v.emplace_back(1, 2);
cout<<v.size()<<endl;
return 0;
}

可以看出,emplace_back的用法比较简单,直接通过构造函数的参数就可以构造对象,因此,也要求对象有对应的构造函数,如果没有对应的构造函数,编译器会报错。如果把上面的构造函数注释掉,在vs2013下编译会报如下错误:

error C2661: “A::A”: 没有重载函数接受 2 个参数

其他容器相应的emplace方法也是类似的。

相对push_back而言,emplace_back更具性能优势。下面通过一个例子来看emplace_back和push_back的性能差异,如代码清单2-5所示:

#include <vector>
#include <map>
#include <string>
#include <iostream>
using namespace std;
struct Complicated
{
int year;
double country;
std::string name;
Complicated(int a, double b, string c):year(a),country(b),name(c)
{
cout<<"is constucted"<<endl;
}
Complicated(const Complicated&other):year(other.year),county(other.
county),name(std::move(other.name))
{
cout<<"is moved"<<endl;
}
};
int main()
{
std::map<int, Complicated> m;
int anInt = 4;
double aDouble = 5.0;
std::string aString = "C++";
cout<<"—insert--"<<endl;
m.insert(std::make_pair(4, Complicated(anInt, aDouble, aString)));
cout<<"—emplace--"<<endl;
// should be easier for the optimizer
m.emplace(4, Complicated(anInt, aDouble, aString));
cout<<"--emplace_back--"<<endl;
vector<Complicated> v;
v.emplace_back(anInt, aDouble, aString);
cout<<"--push_back--"<<endl;
v.push_back(Complicated(anInt, aDouble, aString));
}

输出如下:

--insert--
is constucted
is moved
is moved
--emplace--
is constucted
is moved
--emplace_back--
is constucted
--push_back--
is constucted
is moved
is moved

代码清单2-5测试了map的emplace和vector的emplace_back,用map的insert
方法插入元素时有两次内存移动,而用emplace时只有一次内存移动;用vector
的push_back插入元素时有两次移动内存,而用emplace_back时没有内存移
动,是直接构造的。

可以看到,emplace/emplace_back的性能比之前的insert和push_back的性能要提高很多,我们应该尽量用emplace/emplace_back来代替原来的插入元素的接口以提高性能。需要注意的是,我们还不能完全用emplace_back来取代push_back等老接口,因为在某些场景下并不能直接使用emplace来进行就地构造,比如,当结构体中没有提供相应的构造函数时就不能用emplace了,这时就只能用push_back

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值