C++11中,针对顺序容器(如vector、deque、list),新标准引入了三个新成员:emplace_front、emplace和emplace_back,这些操作构造而不是拷贝元素。这些操作分别对应push_front、insert和push_back,允许我们将元素放置在容器头部、一个指定位置之前或容器尾部。

当调用push或insert成员函数时,我们将元素类型的对象传递给它们,这些对象被拷贝到容器中。而当我们调用一个emplace成员函数时,则是将参数传递给元素类型的构造函数。emplace成员使用这些参数在容器管理的内存空间中直接构造元素。

emplace函数的参数根据元素类型而变化,参数必须与元素类型的构造函数相匹配。emplace函数在容器中直接构造元素。传递给emplace函数的参数必须与元素类型的构造函数相匹配。

其它容器中,std::forward_list中的emplace_after、emplace_front函数,std::map/std::multimap中的emplace、emplace_hint函数,std::set/std::multiset中的emplace、emplace_hint,std::stack中的emplace函数,等emplace相似函数操作也均是构造而不是拷贝元素。

emplace相关函数可以减少内存拷贝和移动。当插入rvalue,它节约了一次move构造,当插入lvalue,它节约了一次copy构造。

下面是从其他文章中copy的测试代码,详细内容介绍可以参考对应的reference:

#include "emplace.hpp"
#include <iostream>
#include <vector>
#include <string>
#include <map>
#include <tuple>
#include <utility> namespace emplace_ { /////////////////////////////////////////////////////////
// reference: http://www.cplusplus.com/reference/vector/vector/emplace_back/
int test_emplace_1()
{
{
/*
template <class... Args>
void emplace_back (Args&&... args);
*/
std::vector<int> myvector = { , , }; myvector.emplace_back();
myvector.emplace_back(); std::cout << "myvector contains:";
for (auto& x : myvector)
std::cout << ' ' << x;
std::cout << '\n';
} {
/*
template <class... Args>
iterator emplace (const_iterator position, Args&&... args);
*/
std::vector<int> myvector = { , , }; auto it = myvector.emplace(myvector.begin() + , );
myvector.emplace(it, );
myvector.emplace(myvector.end(), ); std::cout << "myvector contains:";
for (auto& x : myvector)
std::cout << ' ' << x;
std::cout << '\n';
} return ;
} ///////////////////////////////////////////////////////
// reference: http://en.cppreference.com/w/cpp/container/vector/emplace_back
namespace {
struct President {
std::string name;
std::string country;
int year; President(std::string p_name, std::string p_country, int p_year)
: name(std::move(p_name)), country(std::move(p_country)), year(p_year)
{
std::cout << "I am being constructed.\n";
}
President(President&& other)
: name(std::move(other.name)), country(std::move(other.country)), year(other.year)
{
std::cout << "I am being moved.\n";
}
President& operator=(const President& other) = default;
};
} int test_emplace_2()
{
/*
The following code uses emplace_back to append an object of type President to a std::vector.
It demonstrates how emplace_back forwards parameters to the President constructor and shows
how using emplace_back avoids the extra copy or move operation required when using push_back.
*/
std::vector<President> elections;
std::cout << "emplace_back:\n";
elections.emplace_back("Nelson Mandela", "South Africa", ); std::vector<President> reElections;
std::cout << "\npush_back:\n";
reElections.push_back(President("Franklin Delano Roosevelt", "the USA", )); std::cout << "\nContents:\n";
for (President const& president : elections) {
std::cout << president.name << " was elected president of "
<< president.country << " in " << president.year << ".\n";
}
for (President const& president : reElections) {
std::cout << president.name << " was re-elected president of "
<< president.country << " in " << president.year << ".\n";
} return ;
} ////////////////////////////////////////////////////////////////
// reference: https://stackoverflow.com/questions/4303513/push-back-vs-emplace-back
int test_emplace_3()
{
/*
template <class... Args>
pair<iterator,bool> emplace (Args&&... args);
*/
typedef std::tuple<int, double, std::string> Complicated; std::map<int, Complicated> m;
int anInt = ;
double aDouble = 5.0;
std::string aString = "C++"; // cross your finger so that the optimizer is really good
//m.insert(/*std::make_pair*/std::pair<int, Complicated>(4, Complicated(anInt, aDouble, aString)));
m.insert(std::make_pair(, Complicated(anInt, aDouble, aString))); // should be easier for the optimizer
m.emplace(, Complicated(anInt, aDouble, aString));
/*
std::piecewise_construct: This constant value is passed as the first argument to construct a pair object
to select the constructor form that constructs its members in place by forwarding the elements of two
tuple objects to their respective constructor.
*/
m.emplace(std::piecewise_construct, std::make_tuple(), std::make_tuple(anInt, aDouble, aString)); return ;
} //////////////////////////////////////////////////////////////
// reference: https://corecplusplustutorial.com/difference-between-emplace_back-and-push_back-function/
namespace {
class Dat {
int i;
std::string ss;
char c; public:
Dat(int ii, std::string s, char cc) :i(ii), ss(s), c(cc) { } ~Dat() { }
};
} int test_emplace_4()
{
std::vector<Dat> vec;
vec.reserve(); vec.push_back(Dat(, "New", 'G')); // efficiency lesser
//vec.push_back(678, "Newer", 'O'); // error,push_back can’t accept three arguments
vec.emplace_back(, "Newest", 'D'); // work fine, efficiency is also more return ;
} } // namespace emplace_

C++11 vector使用emplace_back代替push_back的更多相关文章

  1. 编程杂谈——使用emplace_back取代push_back

    近日在YouTube视频上看到关于vector中emplace_back与push_back区别的介绍,深感自己在现代C++中还是有不少遗漏的知识点,遂写了段代码,尝试比较两者的差别. 示例代码 #i ...

  2. C++11使用emplace_back代替push_back

    最近在写一段代码的时候,突然很好奇C++11中对push_back有没有什么改进以增加效率,上网搜了一些资料,发现果然新增了emplace_back方法,比push_back的效率要高很多. 首先,写 ...

  3. 学习 emplace_back() 和 push_back 的区别 emplace_back效率高

    在引入右值引用,转移构造函数,转移复制运算符之前,通常使用push_back()向容器中加入一个右值元素(临时对象)的时候,首先会调用构造函数构造这个临时对象,然后需要调用拷贝构造函数将这个临时对象放 ...

  4. 实战c++中的vector系列--emplace_back造成的引用失效

    上篇将了对于struct或是class为何emplace_back要优越于push_back,可是另一些细节没有提及.今天就谈一谈emplace_back造成的引用失效. 直接撸代码了: #inclu ...

  5. vector 类中的 push_back( ) 函数

    函数名 push_back,算法语言里面的一个函数名,如:   1) c++中的vector头文件里面就有这个push_back函数:   2) 在vector类中作用为在vector尾部加入一个数据 ...

  6. (转)C++11使用emplace_back代替push_back (其中有关于右值引用)

    最近在写一段代码的时候,突然很好奇C++11中对push_back有没有什么改进以增加效率,上网搜了一些资料,发现果然新增了emplace_back方法,比push_back的效率要高很多. 首先,写 ...

  7. C++ std::vector emplace_back 优于 push_back 的理由

    #include <iostream> #include <vector> #include <chrono> #include <windows.h> ...

  8. emplace_back与push_back的区别

    std::vector::emplace_back     C++   Containers library   std::vector   template< class... Args &g ...

  9. 【C/C++开发】emplace_back() 和 push_back 的区别

    在引入右值引用,转移构造函数,转移复制运算符之前,通常使用push_back()向容器中加入一个右值元素(临时对象)的时候,首先会调用构造函数构造这个临时对象,然后需要调用拷贝构造函数将这个临时对象放 ...

随机推荐

  1. redis学习 (key)键,Python操作redis 键 (二)

    # -*- coding: utf-8 -*- import redis #这个redis 连接不能用,请根据自己的需要修改 r =redis.Redis(host=") 1. delete ...

  2. 【Java基础】Java注解简单入门

    注解简单来说就是配置,是特别的配置,之前常用的配置文件,可以用注解替换.然后通过反射去获取注解的信息. 如何定义一个注解 你在IDE中新建一个注解定义,是这样的结构的: package com.nic ...

  3. nginx:not a directory

    项目需要在nginx中提供一个配置文件返回接口的信息,于是就添加了location来实现,本以为很简单的操作,结果访问配置文件时一直返回404,nginx的error log中输出:not a dir ...

  4. crontab 选择编辑器 select-editor

    用root第一次运行 crontab -e 会出现如题的错误,解决方法如下: 1.select-editor 选择编辑器,我选的vim.basic. 2.crontab -e 进入编辑器编辑. 推荐第 ...

  5. 【Zookeeper】连接ZooKeeper的方式

    使用客户端命令连接Zookeeper 连接Server 使用命令./zkCli.sh -server 127.0.0.1:2181 使用JAVA连接使用ZK POM添加引用 <dependenc ...

  6. 【C#】读取Excel中嵌套的Json对象,Json带斜杠的问题(其三)

    除了上一篇中提到的对字符串的字符替换操作,去掉Json中的转义符反斜杠\之外,还发现了更加简单的办法. 就是使用Newtownsoft.Json序列化Json时,将嵌套的Json对象(字符串)转为JO ...

  7. ICE简单介绍及使用示例

    转自:http://blog.csdn.net/zhu2695/article/details/51494664 1.ICE是什么? ICE是ZEROC的开源通信协议产品,它的全称是:The Inte ...

  8. MapReduce 计数器简介

    转自:http://my.oschina.net/leejun2005/blog/276891?utm_source=tuicool&utm_medium=referral 1.计数器 简介 ...

  9. [译] 理解 LSTM(Long Short-Term Memory, LSTM) 网络

    本文译自 Christopher Olah 的博文 Recurrent Neural Networks 人类并不是每时每刻都从一片空白的大脑开始他们的思考.在你阅读这篇文章时候,你都是基于自己已经拥有 ...

  10. Linux操作环境下配置MMIX环境

    一.概述 MMIX用途:高德纳写的<计算机程序设计艺术>,使用 MMIXAL 来编写代码,解释算法. 环境:Ubuntu 桌面版18.04. 二.操作步骤 1,创建MMIX文件夹并切入该文 ...