c++11 vector使用emplace_back代替push_back

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 = { 10, 20, 30 };

    myvector.emplace_back(100);
    myvector.emplace_back(200);

    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 = { 10, 20, 30 };

    auto it = myvector.emplace(myvector.begin() + 1, 100);
    myvector.emplace(it, 200);
    myvector.emplace(myvector.end(), 300);

    std::cout << "myvector contains:";
    for (auto& x : myvector)
        std::cout << ‘ ‘ << x;
    std::cout << ‘\n‘;
}

    return 0;
}

///////////////////////////////////////////////////////
// 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", 1994);

    std::vector<President> reElections;
    std::cout << "\npush_back:\n";
    reElections.push_back(President("Franklin Delano Roosevelt", "the USA", 1936));

    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 0;
}

////////////////////////////////////////////////////////////////
// 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 = 4;
    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(4, Complicated(anInt, aDouble, aString)));

    // should be easier for the optimizer
    m.emplace(6, 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(8), std::make_tuple(anInt, aDouble, aString));

    return 0;
}

//////////////////////////////////////////////////////////////
// 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(3);

    vec.push_back(Dat(89, "New", ‘G‘)); // efficiency lesser
    //vec.push_back(678, "Newer", ‘O‘); // error,push_back can’t accept three arguments
    vec.emplace_back(890, "Newest", ‘D‘); // work fine, efficiency is also more

    return 0;
}

} // namespace emplace_

原文地址:https://www.cnblogs.com/moodlxs/p/10111628.html

时间: 2024-11-09 06:10:30

c++11 vector使用emplace_back代替push_back的相关文章

C++11中emplace_back和push_back比较

1 #include <iostream> 2 #include <vector> 3 using namespace std; 4 5 class A 6 { 7 public: 8 A(int a) 9 :m_a(a) 10 {//构造函数 11 cout<<"A()"<<endl; 12 } 13 A(const A& a) 14 :m_a(a.m_a) 15 {//拷贝构造函数 16 m_count++; 17 cout&

C++11使用emplace_back代替push_back

最近在写一段代码的时候,突然很好奇C++11中对push_back有没有什么改进以增加效率,上网搜了一些资料,发现果然新增了emplace_back方法,比push_back的效率要高很多. 首先,写了一个类用于计时, //time_interval.h #pragma once #include <iostream> #include <memory> #include <string> #ifdef GCC #include <sys/time.h> #

emplace_back与push_back的区别

std::vector::emplace_back C++ Containers library std::vector template< class... Args >void emplace_back( Args&&... args );   (since C++11)       Appends a new element to the end of the container. The element is constructed in-place, i.e. no

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

在引入右值引用,转移构造函数,转移复制运算符之前,通常使用push_back()向容器中加入一个右值元素(临时对象)的时候,首先会调用构造函数构造这个临时对象,然后需要调用拷贝构造函数将这个临时对象放入容器中.原来的临时变量释放.这样造成的问题是临时变量申请的资源就浪费. c++11引入了右值引用,转移构造函数(请看这里)后,push_back()右值时就会调用构造函数和转移构造函数. 在这上面有进一步优化的空间就是使用emplace_back emplace_back   在容器尾部添加一个元

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

上篇将了对于struct或是class为何emplace_back要优越于push_back,但是还有一些细节没有提及.今天就谈一谈emplace_back造成的引用失效. 直接撸代码了: #include <vector> #include <string> #include <iostream> using namespace std; int main() { vector<int> ivec; ivec.emplace_back(1); ivec.e

Part6 数组、指针与字符串 6.10 智能指针 6.11 vector对象

6.10 智能指针C++11 提供智能指针的数据类型,对垃圾回收技术提供了一些支持,实现一定程度的内存管理 unique_ptr:不允许多个指针共享资源,可以用标准库中的move函数转移指针shared_ptr:多个指针共享资源weak_ptr:可复制shared_ptr,但其构造或者释放对资源不产生影响 6.11 vector对象为什么需要vector? 封装任何类型的动态数组,自动创建和删除. 数组下标越界检查. 例6-18 中封装的ArrayOfPoints也提供了类似功能,但只适用于一种

emplace_back() 和 push_back 的区别

在引入右值引用,转移构造函数,转移复制运算符之前,通常使用push_back()向容器中加入一个右值元素(临时对象)的时候,首先会调用构造函数构造这个临时对象,然后需要调用拷贝构造函数将这个临时对象放入容器中.原来的临时变量释放.这样造成的问题是临时变量申请的资源就浪费. 引入了右值引用,转移构造函数后,push_back()右值时就会调用构造函数和转移构造函数. 在这上面有进一步优化的空间就是使用emplace_back. 函数原型 template <class... Args> void

C++提高5 STL算法 :查找,统计,排序,拷贝,替换,算术,集合 |STL 案例:学校演讲比赛介绍

[本文谢绝转载] <大纲> STL 算法 查找算法 adjacent_find()查找容器中重复元素的首地址 distance()根据迭代器,返回元素的下标 binary_search()二分查找:在有序的序列 find   查找函数 find_if 自定义查找函数 统计算法 count 返回容器中相同元素的个数 cout_if 统计大于3的元素个数 排序算法 marge()对两个有序容器组合到另一个容器 sort 自定义排序 random_shuffle 随机洗牌 基本数据类型 random

STL中的常用算法

C++STL 常用算法,使用时包含#include <algorithm> 一.非变异算法 是一组不破坏操作数据的模板函数,用来对序列数据进行逐个处理.元素查找.子序列搜索.统计和匹配.非变异算法具有极为广泛的适用性,基本上可应用与各种容器. 1查找容器元素find 它用于查找等于某值的元素.它在迭代器区间[first,last)(闭开区间)上查找等于value值的元素,如果迭代器i所指的元素满足*i=value,则返回迭代器i:未找到满足条件的元素,返回last.函数原型:find( v1.