std::vector<>.emplace_back

emplace_back() 詳解:C++ 就地構造的效率革命

emplace_back() 是 C++11 引入的容器成員函數,用于在容器尾部就地構造(而非拷貝或移動)元素。這一特性顯著提升了復雜對象的插入效率,尤其適用于構造代價較高的類型。

一、核心優勢:就地構造,避免拷貝

傳統的 push_back() 需要先構造一個臨時對象,再將其拷貝或移動到容器中:

std::vector<std::string> vec;
vec.push_back("hello");  // 步驟1: 構造臨時 string 對象// 步驟2: 移動臨時對象到 vector 中// 步驟3: 銷毀臨時對象

emplace_back() 直接在容器尾部的內存空間中構造對象:

vec.emplace_back("hello");  // 直接在 vector 內存中構造 string 對象// 無需臨時對象,無需拷貝/移動

二、參數與原理

emplace_back() 的原型為:

template <class... Args>
void emplace_back(Args&&... args);
  • 參數Args&&... args 是一個可變參數模板,接受任意數量和類型的參數
  • 原理:通過完美轉發(Perfect Forwarding)將參數傳遞給元素類型的構造函數
  • 效果:直接在容器管理的內存中構造對象,無需臨時對象

三、示例對比

1. 基本類型示例
std::vector<int> vec;
vec.push_back(42);          // 拷貝 int 值
vec.emplace_back(42);       // 直接構造 int 值// 兩者效率相同,因為 int 是 POD 類型
2. 復雜對象示例
class ExpensiveObject {
public:ExpensiveObject(int x, double y) : x(x), y(y) {// 復雜且耗時的初始化操作}// 拷貝構造函數(代價高)ExpensiveObject(const ExpensiveObject& other) = delete;// 移動構造函數(代價高)ExpensiveObject(ExpensiveObject&& other) = delete;
};std::vector<ExpensiveObject> vec;// 錯誤:無法使用 push_back,因為需要拷貝或移動
// vec.push_back(ExpensiveObject(1, 2.0));// 正確:emplace_back 直接構造對象
vec.emplace_back(1, 2.0);  // 直接傳遞構造參數

四、完美轉發與參數匹配

emplace_back() 支持直接傳遞構造所需的參數,包括:

  1. 構造函數參數
  2. 初始化列表
  3. 隱式類型轉換參數
class Person {
public:Person(std::string name, int age) : name(name), age(age) {}private:std::string name;int age;
};std::vector<Person> people;// 使用 emplace_back 傳遞構造參數
people.emplace_back("Alice", 30);  // 直接構造 Person 對象// 使用 push_back 需要顯式構造 Person
people.push_back(Person("Bob", 25));  // 先構造臨時對象,再移動

五、與 push_back() 的關鍵區別

特性emplace_back()push_back()
參數接受構造函數的參數包接受已構造的對象(左值或右值)
構造方式就地構造,無需臨時對象需要先構造臨時對象,再拷貝/移動
支持不可移動類型支持(只要構造函數可用)不支持(必須可拷貝或可移動)
隱式類型轉換支持(直接傳遞轉換所需參數)需顯式轉換(或提供轉換構造函數)

六、注意事項

  1. 內存擴容:若容器需要重新分配內存,emplace_back() 仍需移動所有現有元素

  2. 異常安全:若構造函數拋出異常,容器狀態保持不變

  3. 返回值emplace_back() 不返回新元素的引用(C++17 起 emplace() 返回)

  4. 優先使用場景

    • 插入復雜對象(如包含動態資源的類)
    • 插入需要隱式類型轉換的對象
    • 插入不可拷貝/不可移動的對象

七、進階應用:初始化列表參數

emplace_back() 可以正確處理初始化列表參數:

std::vector<std::vector<int>> matrix;// 使用 emplace_back 和初始化列表
matrix.emplace_back({1, 2, 3});  // 直接構造內部 vector// 等價于
matrix.push_back(std::vector<int>{1, 2, 3});

八、性能測試對比

以下代碼對比了 push_backemplace_back 的性能差異:

#include <chrono>
#include <vector>
#include <string>
#include <iostream>struct ExpensiveToCopy {std::string largeData;ExpensiveToCopy(const char* data) : largeData(data) {}// 模擬高代價的拷貝構造ExpensiveToCopy(const ExpensiveToCopy& other) : largeData(other.largeData) {// 模擬耗時操作for (int i = 0; i < 1000; ++i) {}}
};int main() {std::vector<ExpensiveToCopy> vec;// 測試 push_backauto start = std::chrono::high_resolution_clock::now();for (int i = 0; i < 10000; ++i) {vec.push_back("a very long string that needs to be copied");}auto end = std::chrono::high_resolution_clock::now();std::cout << "push_back time: " << std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count()<< " ms" << std::endl;// 測試 emplace_backvec.clear();start = std::chrono::high_resolution_clock::now();for (int i = 0; i < 10000; ++i) {vec.emplace_back("a very long string that needs to be copied");}end = std::chrono::high_resolution_clock::now();std::cout << "emplace_back time: " << std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count()<< " ms" << std::endl;return 0;
}

九、總結

emplace_back() 是 C++ 容器庫的重要改進,它通過就地構造機制顯著提升了插入效率,尤其適用于:

  1. 構造代價高昂的對象
  2. 需要隱式類型轉換的對象
  3. 不可拷貝/不可移動的對象

在現代 C++ 編程中,建議優先使用 emplace_back() 替代 push_back(),除非需要明確的類型檢查或兼容性保證。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/906331.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/906331.shtml
英文地址,請注明出處:http://en.pswp.cn/news/906331.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Dify實戰案例《AI面試官》更新,支持語音交互+智能知識庫+隨機題庫+敏感詞過濾等...

大模型應用課又更新了&#xff0c;除了之前已經完結的兩門課&#xff08;視頻圖文&#xff09;&#xff1a; 《Spring AI 從入門到精通》《LangChain4j 從入門到精通》 還有目前正在更新的 《Dify 從入門到實戰》 本周也迎來了一大波內容更新&#xff0c;其中就包括今天要介紹…

AGI大模型(29):LangChain Model模型

1 LangChain支持的模型有三大類 大語言模型(LLM) ,也叫Text Model,這些模型將文本字符串作為輸入,并返回文本字符串作為輸出。聊天模型(Chat Model),主要代表Open AI的ChatGPT系列模型。這些模型通常由語言模型支持,但它們的API更加結構化。具體來說,這些模型將聊天消…

動態IP技術在跨境電商中的創新應用與戰略價值解析

在全球化4.0時代&#xff0c;跨境電商正經歷從"流量紅利"向"技術紅利"的深度轉型。動態IP技術作為網絡基礎設施的關鍵組件&#xff0c;正在重塑跨境貿易的運營邏輯。本文將從技術架構、應用場景、創新實踐三個維度&#xff0c;揭示動態IP如何成為跨境電商突…

android雙屏之副屏待機顯示圖片

摘要&#xff1a;android原生有雙屏的機制&#xff0c;但需要芯片廠商適配框架后在底層實現。本文在基于芯發8766已實現底層適配的基礎上&#xff0c;僅針對上層Launcher部分對系統進行改造&#xff0c;從而實現在開機后副屏顯示一張待機圖片。 副屏布局 由于僅顯示一張圖片&…

STM32之中斷

一、提高程序實時性的架構方案 輪詢式 指的是在程序運行時&#xff0c;首先對所有的硬件進行初始化&#xff0c;然后在主程序中寫一個死循環&#xff0c;需要運行的功能按照順序進行執行&#xff0c;輪詢系統是一種簡單可靠的方式&#xff0c;一般適用于在只需要按照順序執行…

LLM應用開發平臺資料

課程和代碼資料 放下面了&#xff0c;自取&#xff1a; https://pan.quark.cn/s/57a9d22d61e9

硬盤健康檢測與性能測試的實踐指南

在日常使用 Windows 系統的過程中&#xff0c;我們常常需要借助各種工具來優化性能、排查問題或管理文件。針對windows工具箱進行實測解析&#xff0c;發現它整合了多種實用功能&#xff0c;能夠幫助用戶更高效地管理計算機。 以下為測試發現的功能特性&#xff1a; 硬件信息查…

正則表達式進階(三):遞歸模式與條件匹配的藝術

在正則表達式的高級應用中&#xff0c;遞歸模式和條件匹配是處理復雜嵌套結構和動態模式的利器。它們突破了傳統正則表達式的線性匹配局限&#xff0c;能夠應對嵌套括號、HTML標簽、上下文依賴等復雜場景。本文將詳細介紹遞歸模式&#xff08;(?>...)、 (?R) 等&#xff0…

從零開始創建React項目及制作頁面

一、React 介紹 React 是一個由 Meta&#xff08;原Facebook&#xff09; 開發和維護的 開源JavaScript庫&#xff0c;主要用于構建用戶界面&#xff08;User Interface, UI&#xff09;。它是前端開發中最流行的工具之一&#xff0c;廣泛應用于單頁應用程序&#xff08;SPA&a…

【前端部署】通過 Nginx 讓局域網用戶訪問你的純前端應用

在日常前端開發中&#xff0c;我們常常需要快速將本地的應用展示給局域網內的同事或測試人員&#xff0c;而傳統的共享方式往往效率不高。本文將指導你輕松地將你的純前端應用&#xff08;無論是 Vue, React, Angular 或原生項目&#xff09;部署到本地&#xff0c;并配置局域網…

【Python裝飾器深潛】從語法糖到元編程的藝術

目錄 ?? 前言??? 技術背景與價值?? 當前技術痛點??? 解決方案概述?? 目標讀者說明?? 一、技術原理剖析?? 核心概念圖解?? 核心作用講解?? 關鍵技術模塊說明?? 技術選型對比??? 二、實戰演示?? 環境配置要求?? 核心代碼實現案例1:基礎計時裝飾器案…

mbed驅動st7789屏幕-硬件選擇及連接(1)

目錄 1.整體介紹 2. 硬件選擇 2.1 mbed L432KC 2.2 ST7789 240*240 1.3寸 3. mbed與st7789的硬件連接 4. 總結 1.整體介紹 我們在使用單片機做一些項目的時候,交互性是最重要的因素。那么對于使用者而言,交互最直接的體現無非就是視覺感知,那么我們希望將項目通過視覺…

SpringBoot集成Jasypt對數據庫連接密碼進行加密、解密

引入依賴 <!--配置密碼加密--><dependency><groupId>com.github.ulisesbocchio</groupId><artifactId>jasypt-spring-boot-starter</artifactId><version>3.0.3</version></dependency><plugin><groupId>c…

分類器引導的條件生成模型

分類器引導的條件生成模型 分類器引導的條件生成模型1. **基本概念**2. **核心思想**3. **實現步驟&#xff08;以擴散模型為例&#xff09;**4. **優點**5. **挑戰與注意事項**6. **應用場景**7. **數學推導**總結 分類器引導的條件生成模型 分類器引導的條件生成模型是一種通…

WPF中的ObjectDataProvider:用于數據綁定的數據源之一

ObjectDataProvider是WPF(Windows Presentation Foundation)中一種強大而靈活的數據綁定源&#xff0c;它允許我們將對象實例、方法結果甚至是構造函數的返回值用作數據源。通過本文&#xff0c;我將深入探討ObjectDataProvider的工作原理、使用場景以及如何在實際應用中發揮其…

lasticsearch 報錯 Document contains at least one immense term 的解決方案

一、問題背景 在使用 Elasticsearch 存儲較大字段數據時&#xff0c;出現如下異常&#xff1a; ElasticsearchStatusException: Elasticsearch exception [typeillegal_argument_exception, reasonDocument contains at least one immense term in field"fieldZgbpka"…

[目標檢測] YOLO系列算法講解

前言 目標檢測就是做到給模型輸入一張圖片或者視頻&#xff0c;模型可以迅速判斷出視頻和圖片里面感興趣的目標所有的位置和它 的類別&#xff0c;而當前最熱門的目標檢測的模型也就是YOLO系列了。 YOLO系列的模型的提出&#xff0c;是為了解決當時目標檢測的模型幀率太低而提…

服務器操作系統時間同步失敗的原因及修復

服務器操作系統時間同步失敗可能導致日志記錄不準確、安全證書失效等問題。以下是常見原因及對應的修復方法&#xff1a; ### 一、時間同步失敗的常見原因 1. **網絡連接問題** - NTP服務器無法訪問&#xff08;防火墻阻止、網絡中斷&#xff09; - DNS解析失敗或網…

Cribl 中function 使用過濾的特殊case:Parser + rename

Cribl 利用function 對parser 進行特殊過濾處理: Parser Function – Fields Filter Expression? When you use the Stream Parser Functions Reserialize option, there is a special option that becomes available, called the Fields Filter Expression. This is basica…

inverse-design-of-grating-coupler-3d

一、設計和優化3D光柵耦合器 1.1 代碼講解 通過預定義的環形間距參數(distances數組),在FDTD中生成橢圓光柵結構,并通過用戶交互確認幾何正確性后,可進一步執行參數掃描優化。 # os:用于操作系統相關功能(如文件路徑操作) import os import sys# lumapi:Lumerical 的…