2015-11-07 74 views
0

我正在使用C++ 11一個工廠模式,其是在我的主()函數的範圍和被調用這樣的:C++壽命返回智能指針

histogram_requests -> AddNewPostfix(Postfix_factory :: get_postfix("Layers", ntuple_reader)); 

Postfix_factory :: get_postfix()是一個靜態成員函數,返回std :: unique_ptr <後綴>。一個示例返回值是:

return std :: move(std :: unique_ptr<Postfix>(new Layers_postfix(ntuple_reader_p))); 

我的第一個問題是,如果這實際上是有效的嗎?返回的指針是否在main()範圍的末尾被銷燬?

第二件事是我想把這個指針傳遞給一個函數。什麼是正確的做法?我的程序編譯當我設置AddNewPostFix()到任何一個的std ::的unique_ptr的自變量類型或的std ::的unique_ptr & &但未能作爲一個簡單的參考。我不想讓我的AddNewPostFix()意外刪除我的指針中的數據,但我不確定這些是否安全。任何人都可以告訴我如何正確和安全地做到這一點?

回答

-1

返回智能指針是好的,直到您決定需要將其保存在不同類型的智能指針中。我只是返回一個原始指針,讓調用者決定它想要做什麼。在你的情況下,std :: move是不必要的。

要將它傳遞給函數,請將函數參數設置爲const T &,並在智能指針上使用解引用運算符。

void someFunction(const T& t) 
{ 
} 

std::unique_ptr<T> t = ...; 
SomeFunction(*t); 
+0

我其實有點困惑。如果沒有** std :: move()**,我的唯一指針中的數據不會被刪除(因爲函數返回後讓unique_ptr的實例超出範圍) –

+0

@AdamHunyadi:是的,它會被刪除。這就是它的重點。但到了這個時候,'someFunction'已經完成了它的工作,所以沒有問題,除非'someFunction'決定在其他地方存儲一個指向'T'的指針,這將是非常邪惡的('global_pointer =&t' )。 –

1
return std :: move(std :: unique_ptr<Postfix>(new Layers_postfix(ntuple_reader_p))); 

有兩件事值得關注的位置:

  1. You don't need std::move in your return statement.

  2. 您應該使用std::make_unique。它僅在C++ 14以後才正式支持,但無論是您的編譯器都支持它,還是您可以輕鬆創建它自己的版本。

是在我main()範圍最終摧毀了返回的指針?

「返回的指針」可以指幾件事情。

std::unique_ptr物體當然被破壞。當範圍結束時,所有本地對象都被銷燬。 std::unique_ptr內的原始指針數據成員也被破壞,但這很簡單。

我想你的真正意思是指向的對象,它由std::unique_ptr管理,即動態分配的Postfix。該對象也將被銷燬,是的,因爲當您的main結束時,std::unique_ptr不會移動到任何位置。

如果Postfix不會被破壞,那麼你會有內存泄漏,std::unique_ptr幾乎沒用,不是嗎?

第二件事是我想將這個指針傳遞給一個函數。什麼是正確的做法?

這個問題太寬泛了。 Herb Sutter曾寫過an entire article about passing smart pointers to functions。這是一篇很長的文章,也有很多有趣的用戶評論。你一定要讀它。這裏是薩特的準則:


,除非你想 使用不通過智能指針作爲函數參數或操縱智能指針本身,如共享或 所有權轉讓。


,*或&,而不是由智能指針由值不想傳遞對象。


使用按值 unique_ptr參數

Express中的「下沉」功能。


只使用一個非const unique_ptr&參數修改unique_ptr


不要使用const unique_ptr&作爲參數;使用widget*代替


快車函數將存儲和使用由值shared_ptr參數共享堆對象的所有權。


只使用一個非const shared_ptr&參數修改shared_ptr。只有當您不確定是否需要複製和共享所有權時,才使用const shared_ptr&作爲參數;否則使用widget*代替(或者如果不可以,則使用widget&)。


我不想讓我的AddNewPostFix()在我的指針意外刪除的數據,但我不知道,要麼這些是安全的。

最安全的事情不會通過指針,而是通過一個Postfix&Postfix const&。當然,人們仍然可以嘗試delete &postfix或採用類似的不良做法。但俗話說,C++防止墨菲,而不是反對馬基雅維利。

下面是一個完整的例子:

#include <memory> 
#include <string> 
#include <iostream> 

struct Postfix 
{ 
    std::string layers; 
    int ntuple_reader; 

    Postfix(std::string const& layers, int ntuple_reader) : 
     layers(layers), 
     ntuple_reader(ntuple_reader) 
    { 
    } 

    ~Postfix() 
    { 
     std::cout << "dtr\n"; 
    } 
}; 

std::unique_ptr<Postfix> get_postfix(std::string const& layers, int ntuple_reader) 
{ 
    return std::make_unique<Postfix>(layers, ntuple_reader); 
} 

void AddNewPostfix(Postfix const& postfix) 
{ 
    std::cout << "AddNewPostfix\n"; 
    // do something with postfix.layers and postfix.ntuple_reader 
} 

int main() 
{ 
    int ntuple_reader = 123; 
    auto postfix_ptr = get_postfix("Layers", ntuple_reader); 
    AddNewPostfix(*postfix_ptr); 
} 

正如你在輸出看到的,Postfix析構函數正確調用在main末。

+0

** 0。 )**我沒有C++ 14的支持,所以我買不起** make_unique()** ** 1。 )**我真的不明白爲什麼我不應該移動unique_ptr。不應該在我的工廠函數結束時將其刪除(並將其轉換爲右值)? ** 2。 )**關於主要問題(我的unique_ptr的生命週期),我真的很好奇它是否一直存在直到主結束(不是如果它在那裏被刪除),但是從你的回答中我推斷它是物理存在的在我的**主()**,所以**你已經回答了我的問題。** ** 3。 )** **謝謝你的例子!** –

+0

@AdamHunyadi:0)'make_unique'很容易編寫你自己。 1)對於具有移動構造函數的類,返回意味着移動。 2)不確定你的意思......'main'與其他函數沒有什麼不同。 3)歡迎您:) –

+0

您給了我一個好主意,在調用析構函數時編寫調試提示符。不幸的是我的析構函數在我的AddNewPostfix()調用後立即調用。這是不正確的。 –