日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

C++ 中emplace_back和push_back差异

發布時間:2023/11/27 生活经验 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C++ 中emplace_back和push_back差异 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
前言

最近看rocskdb源碼,發現了大量的設計模式和C++高級特性,特此補充一下,鞏固基礎。

問題描述

其中關于動態數組的元素添加,代碼中基本將push_back拋棄掉了,全部替換為emplace_back進行元素的添加。

看了一下官網描述:
原來的push_back 一個右值元素的時候 過程分為如下幾步:

  • 使用右值數據類型的構造函數 構造一個臨時對象
  • 調用拷貝構造函數將臨時對象放入 容器中
  • 釋放臨時對象

可以看到以上的三個步驟,臨時對象的資源就沒有用到,而且還多了一次拷貝構造的過程,效率大大降低

后來真針對push_back的優化是引入了右值引用,即在構造出臨時對象之后直接調用轉移構造函數std::move()的形態,將臨時對象的值和地址全部轉移到容器,臨時對象直接就變為空了。
所以c++11的emplace_back是在以上基礎上進一步優化的,在容器的尾部添加元素,而這個元素是原地構造的,不需要調用拷貝構造函數和轉移構造函數了。

測試

測試代碼如下:

#include <iostream>
#include <vector>
#include <unistd.h>using namespace std;class Test {
private:int num;public:Test(int x):num(x){std::cout << "constructed\n";}/*拷貝構造函數*/Test(const Test &obj) {num = obj.num;std::cout << "copy constructed\n";}/*C++11 支持的 轉移構造函數*/Test (Test &&obj) {num = std::move(obj.num);std::cout << "moved constructed\n";}};int main() {vector<Test> arr;vector<Test> t_arr;std::cout << "push_back : Test(1)\n";arr.push_back(1);std::cout << "emplace_back : Test(1)\n";t_arr.emplace_back(1);return 0;
}

輸出如下:

push_back : Test(1)
constructed
moved constructed
emplace_back : Test(1)
constructed

很明顯,這里使用push_back進行了兩次構造(臨時對象的構造 和 轉移構造函數),而empalce_back僅僅構造了臨時對象。

所以emplace_back的性能會優于push_back。

源碼分析

以下源碼是boost庫的最新源代碼,所以push_back的實現也是經過優化的(將拷貝構造函數的實現變更為轉移構造函數)
關于empalce_back的boost源碼實現過程如下:

template <class _Tp, class _Allocator>
template <class... _Args>
inline
#if _LIBCPP_STD_VER > 14
typename vector<_Tp, _Allocator>::reference
#else
void
#endif
vector<_Tp, _Allocator>::emplace_back(_Args&&... __args)
{if (this->__end_ < this->__end_cap()){__RAII_IncreaseAnnotator __annotator(*this);/*傳入可變長參數模版forward進行對象構造,并添加到this代表的容器的末尾*/__alloc_traits::construct(this->__alloc(),_VSTD::__to_raw_pointer(this->__end_),_VSTD::forward<_Args>(__args)...);__annotator.__done();++this->__end_;}else__emplace_back_slow_path(_VSTD::forward<_Args>(__args)...);
#if _LIBCPP_STD_VER > 14return this->back();
#endif
}

push_back的源碼如下:

template <class _Tp, class _Allocator>
inline _LIBCPP_INLINE_VISIBILITY
void
vector<_Tp, _Allocator>::push_back(value_type&& __x)
{if (this->__end_ < this->__end_cap()){/*構造容器指針*/__RAII_IncreaseAnnotator __annotator(*this);/*使用move 的轉移構造函數*/__alloc_traits::construct(this->__alloc(),_VSTD::__to_raw_pointer(this->__end_),_VSTD::move(__x));__annotator.__done();++this->__end_;}else__push_back_slow_path(_VSTD::move(__x));
}

總結

以上是生活随笔為你收集整理的C++ 中emplace_back和push_back差异的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。