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

[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;;:.                      
 */						 



http://www.kler.cn/a/613548.html

相关文章:

  • 鸿蒙学习笔记(3)-像素单位、this指向问题、RelativeContainer布局、@Style装饰器和@Extend装饰器
  • 【NLP 50、损失函数 KL散度】
  • Unity 简单使用Addressables加载SpriteAtlas图集资源
  • java使用aspose添加多个图片到word
  • 3.27-1 pymysql下载及使用
  • Stable Diffusion 基础模型结构超级详解!
  • 用 pytorch 从零开始创建大语言模型(七):根据指示进行微调
  • TextGrad:案例
  • 横扫SQL面试——事件流处理(峰值统计)问题
  • SDL —— 将sdl渲染画面嵌入Qt窗口显示(附:源码)
  • CSS回顾-Flex弹性盒布局
  • Vue $bus被多次触发
  • 【WPF】ListView数据绑定
  • 【AI工具开发】Notepad++插件开发实践:从基础交互到ScintillaCall集成
  • C语言之链表
  • 分布式光伏防逆流如何实现?
  • 每日免费分享之精品wordpress主题系列~DAY16
  • 云原生四重涅槃·破镜篇:混沌工程证道心,九阳真火锻金身
  • 可视化图解算法:递归基础
  • Pyside6介绍和开发第一个程序