当前位置: 首页 > news >正文

C++之std::queue::emplace

std::queue::emplace 是 C++ STL 中 std::queue 容器的成员函数,它用于在队列的末尾就地构造一个新元素。这个函数类似于 std::queue::push,但是 emplace 允许你通过传递参数来构造元素,而不需要显式地创建一个元素对象。

理解 std::queue::emplace

在理解 std::queue::emplace 之前,需要先了解几个重要的概念:

  1. Queue(队列):是一种先进先出(FIFO)的数据结构,允许在队尾添加元素,在队头移除元素。

  2. emplace 操作:是 C++11 引入的特性,允许在容器中就地构造元素,而不需要显式地创建一个对象。

使用 std::queue::emplace

std::queue::emplace 的签名通常如下:

 

cpp

template <typename... Args>
void emplace(Args&&... args);

它接受可变数量的参数 args,这些参数会被传递给元素类型的构造函数。具体地说,当你调用 emplace 时,参数会被传递给底层元素类型的构造函数,从而在队列的末尾构造一个新的元素。

示例

下面是一个简单的示例,展示了如何使用 std::queue::emplace

 

cpp

#include <iostream>
#include <queue>struct MyStruct {int x;std::string str;MyStruct(int a, std::string s) : x(a), str(std::move(s)) {std::cout << "Constructor called with values: " << x << ", " << str << std::endl;}
};int main() {std::queue<MyStruct> myQueue;// 使用 emplace 添加元素myQueue.emplace(10, "Hello");// 使用 emplace 添加另一个元素myQueue.emplace(20, "World");// 遍历队列中的元素(这里只是简单输出,实际应用可以根据需求处理)while (!myQueue.empty()) {auto& front = myQueue.front();std::cout << "Element: " << front.x << ", " << front.str << std::endl;myQueue.pop();}return 0;
}

在这个示例中:

  • MyStruct 是一个简单的结构体,它有一个带参数的构造函数。
  • std::queue<MyStruct> 是一个存储 MyStruct 对象的队列。
  • myQueue.emplace(10, "Hello");myQueue.emplace(20, "World"); 分别在队列中构造了两个 MyStruct 对象。
  • 最后,通过遍历队列并输出每个元素的值来展示结果。

push 的区别

  • std::queue::push 是传统的添加元素方式,需要传递一个已经创建好的对象。
  • std::queue::emplace 则是直接在队列中构造元素,可以避免额外的复制或移动操作,特别是对于非默认构造的对象类型来说更为高效。

总结来说,std::queue::emplace 提供了一种方便和高效的方式来在队列中添加元素,并且避免了不必要的对象复制或移动操作。

那么myQueue.emplace(10, "Hello"); 相当于myQueue.push(MyStruct(10, "Hello"); 吗?

从最终效果来看,myQueue.emplace(10, "Hello");myQueue.push(MyStruct(10, "Hello")); 在结果上是等效的:两种方式都会在队列末尾添加一个 MyStruct 对象。然而,两者之间有一些重要的差异,特别是在性能和对象构造方面:

  1. 对象构造

    • emplace 直接在容器内部构造对象,通过传递给 emplace 的参数来调用元素类型的构造函数。
    • push 则需要先在外部创建一个对象,然后将这个对象复制或移动到容器中。
  2. 性能

    • emplace 可以避免不必要的临时对象创建和复制操作,因此通常比 push 更高效,特别是在元素类型具有复杂构造函数或禁止复制的情况下。
    • push 可能涉及对象的复制或移动,具体取决于元素类型的构造函数和赋值运算符。

让我们通过实际代码来对比一下:

 

cpp

#include <iostream>
#include <queue>
#include <string>struct MyStruct {int x;std::string str;MyStruct(int a, std::string s) : x(a), str(std::move(s)) {std::cout << "Constructor called with values: " << x << ", " << str << std::endl;}// 复制构造函数MyStruct(const MyStruct& other) : x(other.x), str(other.str) {std::cout << "Copy constructor called\n";}// 移动构造函数MyStruct(MyStruct&& other) noexcept : x(other.x), str(std::move(other.str)) {std::cout << "Move constructor called\n";}
};int main() {std::queue<MyStruct> myQueue;// 使用 emplace 添加元素std::cout << "Using emplace:\n";myQueue.emplace(10, "Hello");// 使用 push 添加元素std::cout << "\nUsing push:\n";myQueue.push(MyStruct(20, "World"));return 0;
}

输出可能类似于:

 
Using emplace:
Constructor called with values: 10, HelloUsing push:
Constructor called with values: 20, World
Move constructor called

在使用 emplace 时,构造函数只被调用一次,因为对象是直接在队列中构造的。而在使用 push 时,构造函数和移动构造函数都被调用,这表明对象在创建后被移动到了队列中。

结论

  • emplace 在很多情况下比 push 更高效,因为它可以避免额外的对象复制或移动操作。
  • 如果你希望直接在容器中构造对象并减少开销,应该优先选择 emplace

相关文章:

  • ArcGIS与Excel分区汇总统计三调各地类面积!数据透视表与汇总统计!
  • 在同一个 Blazor 应用中结合 SQL-DB 和 MongoDB
  • windows设置开机启动项
  • 如何卸载宝塔面板?
  • 代码随想三刷二叉树篇4
  • 外观模式(大话设计模式)C/C++版本
  • U-Net for Image Segmentation
  • 【系统架构设计师】二、操作系统知识(操作系统概述|进程管理)
  • 决策树学习
  • 非关系型数据库NoSQL数据层解决方案 之 Mongodb 简介 下载安装 springboot整合与读写操作
  • 2024.06.20【读书笔记】丨生物信息学与功能基因组学(第十六章 真核生物基因组 第三部分)【AI测试版】
  • 【CT】LeetCode手撕—42. 接雨水
  • 计算机网络(谢希仁第六版)| 课后习题与答案 | 物理层 | 题目知识点详细分析
  • sql常用的函数与代码示例
  • vlcplayer for android 源码编译log打印
  • python3.6+scrapy+mysql 爬虫实战
  • Angular Elements 及其运作原理
  • CentOS从零开始部署Nodejs项目
  • css属性的继承、初识值、计算值、当前值、应用值
  • JavaScript类型识别
  • k8s 面向应用开发者的基础命令
  • Linux下的乱码问题
  • mysql中InnoDB引擎中页的概念
  • sublime配置文件
  • UEditor初始化失败(实例已存在,但视图未渲染出来,单页化)
  • 读懂package.json -- 依赖管理
  • 分布式任务队列Celery
  • 诡异!React stopPropagation失灵
  • 互联网大裁员:Java程序员失工作,焉知不能进ali?
  • 基于Mobx的多页面小程序的全局共享状态管理实践
  • 目录与文件属性:编写ls
  • 全栈开发——Linux
  • 如何优雅地使用 Sublime Text
  • 验证码识别技术——15分钟带你突破各种复杂不定长验证码
  • 3月7日云栖精选夜读 | RSA 2019安全大会:企业资产管理成行业新风向标,云上安全占绝对优势 ...
  • 大数据全解:定义、价值及挑战
  • 关于Android全面屏虚拟导航栏的适配总结
  • 没有任何编程基础可以直接学习python语言吗?学会后能够做什么? ...
  • ​经​纬​恒​润​二​面​​三​七​互​娱​一​面​​元​象​二​面​
  • ‌前端列表展示1000条大量数据时,后端通常需要进行一定的处理。‌
  • ###51单片机学习(2)-----如何通过C语言运用延时函数设计LED流水灯
  • #100天计划# 2013年9月29日
  • #pragam once 和 #ifndef 预编译头
  • #QT(串口助手-界面)
  • (1)Android开发优化---------UI优化
  • (1/2) 为了理解 UWP 的启动流程,我从零开始创建了一个 UWP 程序
  • (第8天)保姆级 PL/SQL Developer 安装与配置
  • (第二周)效能测试
  • (六)软件测试分工
  • (面试必看!)锁策略
  • (三分钟了解debug)SLAM研究方向-Debug总结
  • (收藏)Git和Repo扫盲——如何取得Android源代码
  • (四)【Jmeter】 JMeter的界面布局与组件概述
  • (转)原始图像数据和PDF中的图像数据
  • (状压dp)uva 10817 Headmaster's Headache