c++11 中引入了智慧型指標, 同時還有乙個模板函式std::make_shared
可以返回乙個指定型別的std::shared_ptr
, 那與std::shared_ptr
的建構函式相比它能給我們帶來什麼好處呢 ?
shared_ptr
需要維護引用計數的資訊,
如果你通過使用原始的 new 表示式分配物件, 然後傳遞給 shared_ptr (也就是使用 shared_ptr 的建構函式) 的話, shared_ptr 的實現沒有辦法選擇, 而只能單獨的分配控制塊:
如果選擇使用make_shared
的話, 情況就會變成下面這樣:
記憶體分配的動作, 可以一次性完成. 這減少了記憶體分配的次數, 而記憶體分配是代價很高的操作.
關於兩種方式的效能測試可以看這裡 experimenting with c++ std::make_shared
看看下面的**:
1234
void f(const std::shared_ptr& lhs, const std::shared_ptr& rhs)
f(std::shared_ptr(new lhs("foo")),
std::shared_ptr(new rhs("bar")));
c++ 是不保證引數求值順序, 以及內部表示式的求值順序的, 所以可能的執行順序如下:
new lhs(「foo」))
new rhs(「bar」))
std::shared_ptr
std::shared_ptr
好了, 現在我們假設在第 2 步的時候, 丟擲了乙個異常 (比如 out of memory, 總之, rhs 的建構函式異常了), 那麼第一步申請的 lhs 物件記憶體洩露了. 這個問題的核心在於, shared_ptr 沒有立即獲得裸指標.
我們可以用如下方式來修復這個問題.
123
auto lhs = std::shared_ptr(new lhs("foo"));
auto rhs = std::shared_ptr(new rhs("bar"));
f(lhs, rhs);
當然, 推薦的做法是使用std::make_shared
來代替:
1
f(std::make_shared("foo"), std::make_shared("bar"));
make_shared
雖好, 但也存在一些問題, 比如, 當我想要建立的物件沒有公有的建構函式時,make_shared
就無法使用了, 當然我們可以使用一些小技巧來解決這個問題, 比如這裡 how do i call ::std::make_shared on a class with only protected or private constructors?
make_shared
只分配一次記憶體, 這看起來很好. 減少了記憶體分配的開銷. 問題來了,weak_ptr
會保持控制塊(強引用, 以及弱引用的資訊)的生命週期, 而因此連帶著保持了物件分配的記憶體, 只有最後乙個weak_ptr
離開作用域時, 記憶體才會被釋放. 原本強引用減為 0 時就可以釋放的記憶體, 現在變為了強引用, 若引用都減為 0 時才能釋放, 意外的延遲了記憶體釋放的時間. 這對於記憶體要求高的場景來說, 是乙個需要注意的問題. 關於這個問題可以看這裡 make_shared, almost a silver bullet
使用C 11移動複製
製作乙個可移植的使用右值引用的類 c 11標準的最大功能之一是右值引用。此功能允許修改臨時物件,從它們那裡 偷 資源。在c 03中沒有有值引用,但使用boost.move庫,可以寫一些可移植的使用右值引用的 左值 乙個函式或者物件例項。失效值 生命期即將結束的物件。廣義左值 包括左值和失效值。右值 ...
C11編輯器公升級和C11標準使用
c11中的一些特性需要對應的編譯器才能支援。而有些系統預設的編譯器並不支援c11,所以需要4.8及其以上的版本。以下採用c11才支援的std unordered set來進行測試。include include include include include using namespace std ...
使用C 11 實現阻塞佇列
阻塞佇列主要用於執行緒和執行緒之間的通訊。當隊列為空時,從佇列中獲取元素的執行緒將會被掛起 當佇列是滿時,往佇列裡新增元素的執行緒將會掛起。本文使用c 11中的多執行緒庫,實現了乙個帶有最大容量的阻塞佇列。使用visual c 2015編寫。blockqueue.hpp pragma once in...