C 11使用make shared的優勢和劣勢

2022-03-26 14:32:37 字數 2217 閱讀 1126

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

看看下面的**:

123

4

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...