一 介绍

C++11开始,STL的一些容器中增加了emplace和emplace_back成员函数,例如 std::list 和 std::vector。

以 std::vector::emplace_back举例:

template< class... Args >
void emplace_back( Args&&... args ); (C++11 起) (C++17 前)
template< class... Args >
reference emplace_back( Args&&... args ); (C++17 起)

从C++17开始,改变了返回值,返回被插入元素的引用。

emplace_back 添加新元素到容器尾。元素通过 std::allocator_traits::construct 构造,它典型地用布置 new 于容器所提供的位置原位构造元素。参数 args... 以 std::forward<Args>(args)... 转发到构造函数。

二 emplace_back 和 push_back

简单来说,emplace_back是在容器所提供的位置直接构造,而push_back添加一个新元素到vector末尾,然后拷贝或者移动到新元素。

#include <iostream>
#include <vector>class A {public:A() {std::cout << "constructor" << std::endl;}A(int n) {std::cout << "constructor int" << std::endl;}A(const A& a) {std::cout << "copy constructor" << std::endl;}~A() {std::cout << "destructor" << std::endl;}
};int main() {A a;{std::vector<A> vc;vc.reserve(10); // 排除扩容干扰std::cout << std::endl;std::cout << "push_back:" << std::endl;vc.push_back(1);vc.push_back(a);}{std::vector<A> vc1;vc1.reserve(10);std::cout << std::endl;std::cout << "emplace_back:" << std::endl;vc1.emplace_back(1);vc1.emplace_back(a);}std::cin.get();return 0;
}

在push_back中先用参数1构造一个临时的A实例,然后拷贝到vector,最后析构临时的A实例;而emplace_back仅用参数1原位构造了一个A实例。对于插入a,表现一致,都是调用A的拷贝构造函数。

所以在支持emplace_back的场景下,推荐用emplace_back代替push_back。

三 补充(2020.10.16)

以 std::list push_back 为例,定义如下:

// std::list<T,Allocator>::push_back
void push_back( const T& value ); (1)
void push_back( T&& value ); (2)(since C++11)

可以看出,C++11开始,push_back 也增加了移动元素的形式,也就是说:

std::vector<A> vc;// 等同, 均调用A的移动构造函数
{A a;vc.push_back(std::move(a));
}
{A a;vc.emplace_back(std::move(a));
}

为了进一步说明,将二中的例子进行了修改,如下:

#include <iostream>
#include <vector>class A {public:A() { std::cout << "constructor" << std::endl; }A(int n) { std::cout << "constructor int" << std::endl; }A(const A& a) { std::cout << "copy constructor" << std::endl; }A(A&& a) { std::cout << "move constructor" << std::endl; } // 增加移动构造函数~A() { std::cout << "destructor" << std::endl; }
};int main() {{std::vector<A> vc;vc.reserve(10);  // 排除扩容干扰std::cout << std::endl;std::cout << "push_back:" << std::endl;vc.push_back(1);{std::cout << "------------------------" << std::endl;A a;vc.push_back(a); }{std::cout << "------------------------" << std::endl;A a;vc.push_back(std::move(a)); }}{std::vector<A> vc1;vc1.reserve(10);std::cout << std::endl;std::cout << "emplace_back:" << std::endl;vc1.emplace_back(1);{std::cout << "------------------------" << std::endl;A a;vc1.emplace_back(a);}{std::cout << "------------------------" << std::endl;A a;vc1.emplace_back(std::move(a));}}std::cin.get();return 0;
}

结果如下:

push_back:
constructor int
move constructor  // 与上例不同,原因见下
destructor
------------------------
constructor
copy constructor   
destructor
------------------------
constructor
move constructor
destructor
destructor
destructor
destructor

emplace_back:
constructor int
------------------------
constructor
copy constructor
destructor
------------------------
constructor
move constructor
destructor
destructor
destructor
destructor

* 原因:在C++11中,拷贝构造/赋值 和 移动构造/赋值 必须同时提供或者同时不提供,才能保证类同时具有拷贝和移动语义,只声明一种的话,类仅能实现一种语义。参见 C++11 右值引用(2)移动构造和移动赋值函数

STL emplace_back相关推荐

  1. C++ STL: 容器vector源码分析

    文章目录 前言 vector的核心接口 vector push_back实现 vector 的 Allocator vector 的 push_back 总结 前言 vector 是我们C++STL中 ...

  2. C++ STL中的优先队列(priority_queue)使用

    原文:https://www.cnblogs.com/cielosun/p/5654595.html 今天讲一讲优先队列(priority_queue),实际上,它的本质就是一个heap,我从STL中 ...

  3. C++_可变参数模板到emplace_back再到construct再到forward

    C++_可变参数模板到emplace_back再到construct再到forward 1.可变参数模板 具体定义如下图所示: 编写一个可变参数版本: 1.1sizeof-运算符 2.emplace_ ...

  4. C++ STL容器——序列式容器(array、vector、deque、list)

    概述 1.C++ STL的容器分为三种,序列式容器,关联式容器,无序式容器,这里先说说常用的序列式容器. 2.array,vector,deque,list,forward_list这几种都是序列式容 ...

  5. c语言stl模板,c/c++开发分享C++ 标准模板库 STL 顺序容器详解

    c++ 标准模板库 stl 顺序容器 容器 顺序性 重复性 支持迭代器 vector 动态数组 无序 可重复 随机访问迭代器 deque 双向队列 无序 可重复 随机访问迭代器 list 双向链表 无 ...

  6. C++ STL实现的优先队列( priority_queue )

    本文参考的源码版本:gcc version 8.1.0 (x86_64-posix-seh-rev0, Built by MinGW-W64 project). priority_queue 本质是容 ...

  7. STL源码剖析 基本算法 < stl_algobase.h >

    注意事项 : 实际使用的时候,使用的是<algorithm>这个头文件,不是题目中的< stl_algobase.h > equal函数 如果两个序列在[firsLlast) ...

  8. string类的erase函数属于stl吗_探索STL容器:vector

    用了这么久的 vector ,今天终于有时间来看下STL的实现源码了,开心?~ 最近几个月在刷 leetcode ,用的较多的数据结构就是STL里面的 vector 了,相比较于直接的 array 数 ...

  9. STL之Vector(Linux内核)完整实现

    自上次写了map之后对Vector比较感兴趣,由于对Vector理解不是很深刻,利用业余时间从Linux系统中拷贝出完整的Vector代码进行学习参考,并对一部分做了修改可以在Windows系统运行. ...

  10. 浅谈C++ STL中的优先队列(priority_queue)

    2019独角兽企业重金招聘Python工程师标准>>> 从我以前的博文能看出来,我是一个队列爱好者,很多并不是一定需要用队列实现的算法我也会采用队列实现,主要是由于队列和人的直觉思维 ...

最新文章

  1. 初探swift语言的学习笔记五(线程)
  2. npm ERR! cb.apply is not a function npm ERR! A complete log of this run can be found in: npm ERR!
  3. 设计模式:依赖倒置原则
  4. 把ipa文件上传到服务器,windows电脑上传ipa到appstore的详细流程
  5. 2016CCPC网络赛赛后总结——回顾与反思
  6. 数学中的一朵“奇葩”——四元数
  7. 怎么加载文件_Java虚拟机从入门到入土之JVM的类加载机制
  8. IndexAction.java (Java之负基础实战)
  9. spring循环依赖 第二讲
  10. 业界软件测试工程师认证(ISTQB)
  11. 程序员,如何做好工作复盘?
  12. wifi(华硕天选2)找不到怎么办
  13. Android SqlDelight详解和Demo例子
  14. linux挂死oops定位问题
  15. MFC使用CFile类进行输入输出到文本文件
  16. 2022最新中高阶Android面试题总结,Android面试题库
  17. aspf ftp_FTP主动模式和被动模式
  18. 工具分享:elasticsearch-7.3.1请自行下载(Linux、windows_64)(附下载链接)
  19. css案例 - 评分效果的星星✨外衣
  20. PC站跳转M站的方法

热门文章

  1. Zynga公布2021年第二季度财务业绩
  2. 微信小程序中使用Echarts 折线图、柱形图、饼状图
  3. 超级表格pk王者农药,今天你五杀了么?
  4. MPC-HC视频播放器
  5. CentOS 7 校对时间 修改时区
  6. 统信UOS应用商店十月活动
  7. InsecureProgramming-master——abo1
  8. 2018电视剧行业调研报告-趋势篇
  9. ECU重编程流程(UDS)
  10. YOLOV5网络结构