C++——Vector:push_back和emplace_back的区别,测试写入1GB大数据时的性能差距

这篇具有很好参考价值的文章主要介绍了C++——Vector:push_back和emplace_back的区别,测试写入1GB大数据时的性能差距。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

什么是emplace_back

emplace_back是C++11引入的STL容器成员函数。emplace操作只执行构造而不执行拷贝构造。
如何理解上面这句话?先来看一个场景。

class test
{
public:
    test(){}
    test(int i){ std::cout << "test(int i)" << std::endl; }
    test(const test& _test){ std::cout << "test(const test& _test)" << std::endl; }
};

int main()
{
    std::vector<test> arr;
    arr.reserve(5);

    arr.push_back(1);
    arr.emplace_back(1);

    return 0;
}

test类显式写出了三个构造函数,分别是无参构造、单参数构造、拷贝构造。因为C++中单参数的构造函数支持隐式类型转换,因此可以拿一个整型构造一个test对象。除非用explicit修饰构造函数,表示禁止隐式类型转换构造。

test(int i)
test(const test& _test)
test(int i)

这是上述代码的运行结果,可以看到push_back中,会用整数1构造一个test对象,再通过拷贝构造再构造一个对象,这才是插入到arr数组中的对象。
而emplace_back只有一次隐式类型转换的构造,因为emplace是直接使用参数在容器管理的内存空间中直接构造元素,因此没有拷贝的操作,在一定程度上提高了效率。

写入大数据时的性能差异

class test
{
public:
    test(){}
    test(int i){ }
    test(const test& _test){ }
};

void test_push_back()
{
    clock_t start = clock();
    std::vector<test> arr;
    arr.reserve(1000000000);

    for(int i = 0; i < 1000000000; i++)
    {
        arr.push_back(1);
    }

    std::cout <<"耗时:"<< (clock() - start) << std::endl;
    /*
        耗时:24.41秒
    */
}

void test_emplace_back()
{
    clock_t start = clock();
    std::vector<test> arr;
    arr.reserve(1000000000);

    for(int i = 0; i < 1000000000; i++)
    {
        arr.emplace_back(1);
    }

    std::cout <<"耗时:"<< (clock() - start) << std::endl;
    /*
        耗时:15.86秒
    */
}

int main()
{
    test_push_back();
    test_emplace_back();
    return 0;
}

shell脚本用于实时监控进程运行状况
while true; do ps aux | head -1 ; ps aux | grep a.out; printf "——————————————————————\n\n" ; sleep 1; done

一个栈上的test对象的大小是1个字节,因为test类没有存储对象成员,而编译器为了表明一个test对象存在,需要用1字节作为占位符。
109 个对象即1亿个,1个对象是1个字节。后台检测到有982456个字节,即大约1GB。可以看到,插入109个test对象的时候,差距大概是10秒钟。

应用场景

你可能说,这种优化有什么用,有什么类会允许隐式类型转换,还可能插入的时候不显式构造?
没错,就是string。

void test_push_back()
{
    clock_t start = clock();
    std::vector<std::string> arr;
    arr.reserve(1000000000);

    for(int i = 0; i < 100000000; i++)
    {
        arr.push_back("Hello World !!! Hello World !!! Hello World !!! Hello World !!! Hello World !!! Hello World !!! Hello World !!! Hello World !!! Hello World !!! ");
    }

    std::cout <<"耗时:"<< (clock() - start) << std::endl;
    /*
        耗时:25.66秒
    */
}

void test_emplace_back()
{
    clock_t start = clock();
    std::vector<std::string> arr;
    arr.reserve(1000000000);

    for(int i = 0; i < 100000000; i++)
    {
        arr.emplace_back("Hello World !!! Hello World !!! Hello World !!! Hello World !!! Hello World !!! Hello World !!! Hello World !!! Hello World !!! Hello World !!! ");
    }

    std::cout <<"耗时:"<< (clock() - start) << std::endl;
    /*
        耗时:16.20秒
    */
}
耗时:20.39秒
耗时:17.87

可是差距好像并不是很大=-=

综上所述:可能提升有限,但是能使用emplace_back还是不使用push_back了。文章来源地址https://www.toymoban.com/news/detail-690862.html

到了这里,关于C++——Vector:push_back和emplace_back的区别,测试写入1GB大数据时的性能差距的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【C++】链表(list)的使用以及与vector的区别

    在 C++ 中, std::list 是标准库提供的一个容器类,用于将数据进行链式存储。 链表 (list)是一种物理存储单元上非连续的存储结构,数据元素的逻辑顺序是通过链表中的指针链接实现的。 链表的组成:链表由一系列 结点 组成。 结点的组成:1.存储数据元素的 数据域 2.存储

    2024年02月06日
    浏览(32)
  • C++之map的emplace与pair插入键值对用例(一百七十四)

    简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长! 优质专栏: Audio工程师进阶系列 【 原创干货持续更新中…… 】🚀 人生格言: 人生从来没有捷径,只有行动才是治疗恐惧和懒惰的唯一良药. 更多原创,欢迎关注:An

    2024年02月12日
    浏览(31)
  • C++-queue:queue基本用法【q.push(x)、q.front()、q.back()、q.pop()、q.size()、q.empty()】

    一种操作受限制的线性表 队列是一种线性储存数据结构,数据元素遵循“先进先出”(First in First out (FIFO))的原则 添加元素在队尾(只允许添加元素)实现,删除元素在对头(只允许删除元素)实现 排队 挂号 消息队列 广度优先搜索等符合队列特点的操作 基于数组的

    2024年02月03日
    浏览(28)
  • “Pull”和“Push”支付的区别

    下图展示了“Pull”和“Push”支付的工作原理。 当我们在商家处刷信用卡/借记卡时,这是一种“Pull”支付,资金从持卡人的账户发送到商家。商家从持卡人的账户中取款,而持卡人批准交易。 通过Visa Direct或Mastercard Send,推送支付可以实现商家、公司和政府的付款。 Step 1

    2024年02月08日
    浏览(36)
  • ArrayList和Vector及LinkedList的区别

    1.ArrayList和Vector的区别 第一句话:ArrayList和Vector底层都是数组实现的,初始容量都为10;在ArrayList的底层,是通过定义一个DEFAULT_CAPACITY的常量来指定的,而Vector的底层,是直接在空参构造中,通过写死了一个this(10)来指定的; 第二句话:Vector大部分方法的底层实现,都加了 s

    2024年02月11日
    浏览(30)
  • 【iOS】push与present Controller的区别

    iOS推出与退出界面有两种方式——push与present,接下来笔者分别介绍这两种方式 presentedViewController和presentingViewController是UIViewController里面的两个属性 PresentedViewController 与 PresentingViewController区别 presentedViewController:The view controller that was presented by this view controller or its nearest a

    2024年02月09日
    浏览(21)
  • git中push和pull的区别是什么

    git中push和pull的区别: 1、“git push”命令是将本地库中的最新信息发送给远程库,用于将本地分支的更新,推送到远程主机; 2、“git pull”命令是从远程获取最新版本到本地库,用于从另一个存储库或本地分支获取并集成整合。 git push与git pull是一对推送/拉取分支的git命令。

    2024年02月03日
    浏览(26)
  • list和vector容器的插入与访问操作区别

    std::list 和 std::vector 是C++中的两种常见数据结构,它们在不同的使用场景下各有优势。 std::vector 的内部实现是动态数组,它在连续的内存块中存储数据。这使得 std::vector 在 访问元素时具有非常高的效率,因为可以直接通过索引来访问元素,时间复杂度为O(1) 。然而, std::ve

    2024年02月13日
    浏览(30)
  • unity_Vector3.up 和 transform.up 的区别

    Vector3.up : 即 Vector3(0, 1, 0) Vector3.down : 即 Vector3(0, -1, 0) Vector3.forward : 即 Vector3(0, 0, 1) Vector3.back : 即 Vector3(0, 0, -1) Vector3.right : 即 Vector3(1,0, 0) Vector3.left : 即 Vector3(-1, 0, 0) 在 Scene 中画线(脚本挂给Cube)  结果 transform.up : 即 Vector3.up transform.forward : 即 Vector3.forward tra

    2023年04月14日
    浏览(20)
  • STL 关于vector的细节,vector模拟实现【C++】

    _start指向容器的头,_finish指向容器当中 有效数据 的下一个位置,_endofstorage指向整个容器的尾 先开辟一块与该容器大小相同的空间,然后将该容器当中的数据一个个拷贝过来即可,最后更新_finish和_endofstorage的值即可。 深拷贝版本一: 注意: 不能使用memcpy函数 , 如果vec

    2024年02月15日
    浏览(31)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包