2016-12-21 54 views
1

我有以下簡單的代碼,而我還沒有發現其中的智能指針用於這個簡單的例子一個線程,而是複製對象:智能指針 - 的unique_ptr的堆棧分配的變量

int main() 
{ 
    int i = 1; 

    std::unique_ptr<int> p1(&i); 
    *p1 = 2; 

    return 0; 
} 

這當指針超出範圍時導致_BLOCK_TYPE_IS_INVALID。如果我撥打p1.release(),代碼工作正常,我不會收到此錯誤。我認爲這樣的指針足夠聰明來處理懸掛指針?

另一種方法是,如果我有我的一份,這並沒有給上述錯誤:

std::unique_ptr<int> p1(new int(i)); 

什麼是這裏使用智能指針,在這裏我不想執行本地的優勢複製?

如果我是使用原始指針:

int i = 1; 
int *p1 = &i; 
*p1 = 2; 

我不會得到一個錯誤,即使我不代碼:

p1 = nullptr; 

回答

8

std::unique_ptr s爲處理動態分配的內存;他們說當你構建一個指針的時候獲取指針的所有權。您的int i;在堆棧上,因此不會動態分配;它的所有權不能從堆棧中拿走。當unique_ptr析構函數試圖對delete指針給予它(因爲它認爲沒有人擁有它),你會得到該錯誤,因爲delete只能用於使用new創建的指針。

考慮到你的簡短例子,我不知道這是什麼上下文......但你應該使用原始指針(或者複製,如你所說)爲堆棧分配的變量。

+0

謝謝你們,這是有道理的。另外,爲什麼我不能只做p1 = nullptr而不是p1.release()。我明白,release()返回一個指向託管對象的指針並釋放所有權。 p1.reset()取代了被管理對象,所以對於棧分配的變量來說這是非法的。但爲什麼p1 = nullptr編譯,但引發異常? – c0der

+1

使用['=']指定'unique_ptr'(http://www.cplusplus.com/reference/memory/unique_ptr/operator=/)基本上與調用['reset'](http:// www .cplusplus.com/reference/memory/unique_ptr/reset /),並銷燬先前保存的指針。使用['release'](http://www.cplusplus.com/reference/memory/unique_ptr/release/)會放棄指針的所有權,而不會破壞它。 – qxz

+0

'p1 = nullptr'是一個賦值,p1應該清理它的指針然後保存nullptr。這是業主需要做的。 'p1.release()'是放棄它的「所有權」並將它的控制指針返回給其他人,而不再管理,所以它不會清理它。 –

0

由@qzx提供的答案是你在你的代碼

一個額外的東西約std::unique_ptr<>使用所舉報的問題的主要原因。您應該始終嘗試使用std::make_unique<>()創建一個std::unique_ptr。它有時通過提供適當的編譯錯誤來幫助恰當地使用這個指針。

例如,如果您更改與std::make_unique<>

int i = 1; 
std::unique_ptr<int> p1 = make_unique<int>(&i); 

那麼大多數編譯器會給出錯誤的

can't convert int* to int 

它會幫助你使用它創建一個全新的副本,上面的代碼整數的所有權由std::unique_ptr<>

int i = 1; 
std::unique_ptr<int> p1 = make_unique<int>(i); 
*p1 = 2; 

此代碼有效。

+0

因此,在這種情況下使用智能指針沒有什麼好處,而不是對i,int&p = i的引用,因爲&p在超出範圍時被解除引用。例如,我想最好在類聲明中使用智能指針。 make_unique可用於C++ 14以上?我的VS2012編譯器無法識別它。 – c0der