2014-04-01 194 views
1

背景

我寫一個networkprotocol驅動器和具有功能write(std::shared_ptr<package> package),其中packagestd::array<buffer_ptr,2>(0 =>頭,1 =>體)。爲了方便,我想編寫一個函數write(buffer_ptr body),它自動生成頭並調用write的第一種形式。要做到這一點,我想我們std::make_shared,但我有問題從make_shared呼叫初始化std::array初始化的std ::陣列make_shared

代碼

typedef std::shared_ptr<std::vector<uint8_t>> buffer_ptr; 
typedef std::array<buffer_ptr, 2> package_t; 
typedef std::shared_ptr<package_t> package_ptr; 

void connection::write(package_ptr package) { 
    ... //do stuff 
} 

void connection::write(buffer_ptr body) { 
    buffer_ptr header = buildHeader(body); 
    write(std::make_shared<package_t>(???)) //here I want to initialize the array with {header,body} 
} 

我想的是什麼???

(這導致編譯器錯誤)

{header, body} 
{{header, body}} 
std::initializer_list<buffer_ptr>{header, body} 

問:

  1. 是否有解決方案,使這項工作還是我寫的東西,如:

    package_ptr包=新包{header,body}; write(package);

    1.b)不得不求助於package_ptr(new package)? (記得使共享分配存儲器的指針,並且在一個組塊中的情況下,以節省存儲器請求)

  2. Cppreference是讀取:

    此外,F(shared_ptr的(新INT(42)) ,g())會導致內存泄漏 如果g拋出異常。如果使用make_shared爲 ,則不存在此問題。

    爲什麼內存泄漏(可能int(42)g之前構造被調用,gshared_ptr之前調用被調用)?那麼來自1.的替代代碼會遭受這種潛在的泄漏嗎?

+2

'寫(STD :: make_shared (package_t {標題,正文}) );' – Cubbi

+0

@Cubbi很好!微軟編譯器不喜歡它,雖然:( –

+0

@Cubbi:如果'make_shared'拋出(即內存不足)會發生什麼?已經構建的'package_t'被泄露? – ted

回答

1

第一:

array沒有顯式聲明的構造函數。特別是,它沒有一個構造函數來獲取初始化器列表。

我覺得一個乾淨的方法是避免在代碼中明確new,而讓標準功能:

package_t p = {header, body}; 
write(std::make_shared<package_t>(p)); 

如果既沒有new也不std::shared_ptr的代碼會更好看:

package_t p = {header, body}; 
write(p); 

其次,Cppreference.com記載:

此外,如果g拋出異常,f(shared_ptr(new int(42)),g()) 可能導致內存泄漏。如果使用make_shared,則此問題不存在 。

標準沒有規定評估函數的順序參數和表達式可以按任何順序評估,只要它們產生相同的結果即可。

f(shared_ptr(new int(42)), g()) 

new int(42)必須先shared_ptr()但不g(),這可能導致泄漏,如果g拋出。

f(make_shared<int>(42), g()) 

分配發生內部make_shared。如果gmake_shared之前被調用,並且如果拋出,內存永遠不會被分配。

如果make_sharedg之前調用,如果g兩罰全中,shared_ptr對象將已經創建成功了,它的破壞是因爲RAII的保證

+0

'shared_pointer'必須保持,因爲它經歷了異步寫入,並且指針用於在寫入調用回調後釋放標頭/主體 – ted