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

[C++开发经验总结]何时用push?/何时用emplace?

标题:[C++开发经验总结]何时用push?/何时用emplace?
@水墨不写bug

在这里插入图片描述


文章目录

  • 一、push与emplace辨析
    • 1. `push` 方法
    • 2. `emplace` 方法
    • 3. 注意事项
  • 二、全文总结:


一、push与emplace辨析

1. push 方法

  • 适用场景
    • 当你已经有一个对象实例,并且你想把它添加到容器中时使用。
  • 语法
    • push_back:用于在容器末尾添加元素。
    • push_front:用于在容器开头添加元素(适用于std::dequestd::list)。
  • 示例
      string data = "data";
      vec.push_back(data);      // 保留原对象,拷贝到容器
      vec.push_back(std::move(data)); // 转移资源到容器
    

2. emplace 方法

  • 适用场景
    • 当你想在容器中直接构造对象时使用,避免了不必要的临时对象创建和拷贝。
  • 语法
    • emplace_back:在容器末尾直接构造对象。
    • emplace_front:在容器开头直接构造对象(适用于std::dequestd::list)。
  • 示例
      std::map<int, std::string> myMap;
      myMap.emplace(4, "fast");    // 直接在 map 中构造 pair
      
      std::vector<std::string> vec;
      vec.emplace_back("direct");  // 直接构造,无临时对象
    

3. 注意事项

  • emplace 直接在容器中构造对象,通常比 push 更高效,因为它避免了临时对象的创建和拷贝。
  • 在使用 push 时,容器需要调用拷贝构造函数或移动构造函数来添加元素。
  • 需要注意,如果强制对还有用的变量move,那么move后的变量会处于一种有效但未指定状态,不可依赖其内容

但是并不是所有的变量move之后都不可使用其内容,考虑如下的实例:

void MoveBuiltinTypes()
{
    cout<<"----------------"<<endl;

    std::vector<int> vec;
    int a = 10;
    vec.push_back(std::move(a)); // 使用push_back将已有对象a添加到容器中
    cout<<"a:"<<a<<endl;
}
void MoveCustomTypes()
{
    cout<<"----------------"<<endl;
    std::vector<std::string> vec;
    std::string s = "hello";
    vec.push_back(s);        // 拷贝构造:复制 s 到容器中
    vec.push_back(std::move(s)); // 移动构造:转移 s 的资源到容器中
    cout<<"s:"<<s<<endl;
    cout<<"s.size():"<<s.size()<<endl;
}
int main()
{
    MoveBuiltinTypes();
    MoveCustomTypes();
    return 0;
}

运行结果:
在这里插入图片描述string类型的变量s在move之后,内容被清空,size被置为0;内置类型int a变量在move之后,值没有发生变化。这样是为了尽可能提高效率,string调用移动构造,把s内容交换到vec内部;而a变量不占用堆区资源,不改变a的值反而提高了效率。
于是可以推断string的移动构造类似于:

string(string&& other) noexcept {
    data = other.data;    // 转移指针
    size = other.size;
    capacity = other.capacity;
    other.data = nullptr; // 原对象指针置空
    other.size = 0;
    other.capacity = 0;
}

二、全文总结:

(考虑占有资源的自定义类型)

push:对象已经存在,用push。传参时候,传值调用拷贝构造,可能引发拷贝或移动开销;传引用则需要考虑是直接传引用还是传const引用。
emplace:直接在容器内部构造对象,避免临时对象开销,性能更优。

优先使用 emplace:
当元素未构造且可直接通过参数构造时,优先使用 emplace 以提升性能。

    myMap.emplace(42, "answer");  // 优于 myMap.insert({42, "answer"});

使用 push 的场景:

  • 需要保留原对象(拷贝语义)。
  • 需要显式移动资源(移动语义)。
  • 兼容旧代码或特定接口要求。


转载请注明出处


/***                                                                          
 *          .,:,,,                                        .::,,,::.          
 *        .::::,,;;,                                  .,;;:,,....:i:         
 *        :i,.::::,;i:.      ....,,:::::::::,....   .;i:,.  ......;i.        
 *        :;..:::;::::i;,,:::;:,,,,,,,,,,..,.,,:::iri:. .,:irsr:,.;i.        
 *        ;;..,::::;;;;ri,,,.                    ..,,:;s1s1ssrr;,.;r,        
 *        :;. ,::;ii;:,     . ...................     .;iirri;;;,,;i,        
 *        ,i. .;ri:.   ... ............................  .,,:;:,,,;i:        
 *        :s,.;r:... ....................................... .::;::s;        
 *        ,1r::. .............,,,.,,:,,........................,;iir;        
 *        ,s;...........     ..::.,;:,,.          ...............,;1s        
 *       :i,..,.              .,:,,::,.          .......... .......;1,       
 *      ir,....:rrssr;:,       ,,.,::.     .r5S9989398G95hr;. ....,.:s,      
 *     ;r,..,s9855513XHAG3i   .,,,,,,,.  ,S931,.,,.;s;s&BHHA8s.,..,..:r:     
 *    :r;..rGGh,  :SAG;;G@BS:.,,,,,,,,,.r83:      hHH1sXMBHHHM3..,,,,.ir.    
 *   ,si,.1GS,   sBMAAX&MBMB5,,,,,,:,,.:&8       3@HXHBMBHBBH#X,.,,,,,,rr    
 *   ;1:,,SH:   .A@&&B#&8H#BS,,,,,,,,,.,5XS,     3@MHABM&59M#As..,,,,:,is,   
 *  .rr,,,;9&1   hBHHBB&8AMGr,,,,,,,,,,,:h&&9s;   r9&BMHBHMB9:  . .,,,,;ri.  
 *  :1:....:5&XSi;r8BMBHHA9r:,......,,,,:ii19GG88899XHHH&GSr.      ...,:rs.  
 *  ;s.     .:sS8G8GG889hi.        ....,,:;:,.:irssrriii:,.        ...,,i1,  
 *  ;1,         ..,....,,isssi;,        .,,.                      ....,.i1,  
 *  ;h:               i9HHBMBBHAX9:         .                     ...,,,rs,  
 *  ,1i..            :A#MBBBBMHB##s                             ....,,,;si.  
 *  .r1,..        ,..;3BMBBBHBB#Bh.     ..                    ....,,,,,i1;   
 *   :h;..       .,..;,1XBMMMMBXs,.,, .. :: ,.               ....,,,,,,ss.   
 *    ih: ..    .;;;, ;;:s58A3i,..    ,. ,.:,,.             ...,,,,,:,s1,    
 *    .s1,....   .,;sh,  ,iSAXs;.    ,.  ,,.i85            ...,,,,,,:i1;     
 *     .rh: ...     rXG9XBBM#M#MHAX3hss13&&HHXr         .....,,,,,,,ih;      
 *      .s5: .....    i598X&&A&AAAAAA&XG851r:       ........,,,,:,,sh;       
 *      . ihr, ...  .         ..                    ........,,,,,;11:.       
 *         ,s1i. ...  ..,,,..,,,.,,.,,.,..       ........,,.,,.;s5i.         
 *          .:s1r,......................       ..............;shs,           
 *          . .:shr:.  ....                 ..............,ishs.             
 *              .,issr;,... ...........................,is1s;.               
 *                 .,is1si;:,....................,:;ir1sr;,                  
 *                    ..:isssssrrii;::::::;;iirsssssr;:..                    
 *                         .,::iiirsssssssssrri;;:.                      
 */						 


相关文章:

  • Flask项目部署:Flask + uWSGI + Nginx
  • 维智 Harmony NEXT 定位 SDK:鸿蒙生态下的空间智能应用实践
  • 软件兼容性测试的矩阵爆炸问题有哪些解决方案
  • Unity UGUI - 六大基础组件
  • GNSS数据说明-RTCM
  • 简单谈谈很火的MCP( Model Context Protocol,模型上下文协议)
  • 【Sql Server】在SQL Server中生成雪花ID(Snowflake ID)
  • HarmonyOS NEXT状态管理实践
  • Yolo_v8的安装测试
  • 以太坊主网 PoS 节点搭建指南
  • 天锐蓝盾终端安全防护——企业终端设备安全管控
  • 如何让 history 记录命令执行时间?Linux/macOS 终端时间戳设置指南
  • 嵌入式linux系统中对应的文件锁详细实现方法
  • AI-人工智能-实现将静态图片和视频合成为类似iPhone的Live Photo(动态照片)效果
  • iPhone mini,永远再见了
  • 量子力学:从经典物理危机到思维革命的新纪元
  • 6.Excel:通过 Power Query 处理从网上获取的数据
  • 西门子s7协议
  • 自然语言处理(15:RNNLM的学习和评价(整个第4章大总结))
  • Linux子系统 - USB描述符结构体
  • 中国建设注册管理中心网站首页/网络推广营销公司
  • 做鸡鸭冻品生意的都在使用的网站/建站工具
  • 找个做网站的/推广网站都有哪些
  • wordpress网站名称函数/谷歌优化技巧
  • 网站结构怎么做适合优化/西安百度公司官网
  • 淘宝手机版网页/天津关键词优化平台