2017-03-04 412 views
1

我想要真正從C++ 98移到C++ 11和更新的版本。我已將大部分新東西包裹起來,但我仍不確定unique_ptr的正確用法。在類成員中正確使用unique_ptr

考慮下面的例子,其中類A有一個unique_ptr成員(我以前會使用原始指針!)。這個成員變量應該在用戶需要時通過在其他地方調用一個函數(而不是類的一部分)來分配。這是正確的用法嗎?如果不是,最好的選擇是什麼?

class A { 
private: 
    unique_ptr<MyType> mt; 
public: 
    void initStuff() { 
     mt.reset(std::move(StaticFuncSomewhereElese::generateMyType())); 
    } 
}; 

MyType* StaticFuncSomewhereElese::generateMyType() { 
    MyType* temp = new MyType(...); 
    //do stuff to temp (read file or something...) 
    return temp; 
} 
+2

你不需要'std :: move'那裏,原始指針不能被移動。 – emlai

+0

@tuple_cat但是,這編譯和運行完美 –

+0

@SaeidYazdani雖然你不需要它。而是使用'std :: make_unique()'。 –

回答

3

你的代碼工作正常(雖然冗餘* move可省略),但它會更好,儘早構建unique_ptr

classss A { 
private: 
    std::unique_ptr<MyType> mt; 
public: 
    void initStuff() { 
     mt = StaticFuncSomewhereElese::generateMyType(); 
    } 
}; 

std::unique_ptr<MyType> StaticFuncSomewhereElese::generateMyType() { 
    auto temp = std::make_unique<MyType>(…); 
    // `make_unique` is C++14 (although trivially implementable in C++11). 
    // Here's an alternative without `make_unique`: 
    // std::unique_ptr<MyType> temp(new MyType(…)); 

    //do stuff to temp (read file or something...) 
    return temp; 
} 

這種方式很明顯的回報調用者必須刪除generateMyType的值,並且內存泄漏的可能性較小(例如,如果generateMyType提前返回)。

*的move是多餘的,因爲:

  1. 原始指針不能移動。
  2. 無論如何,generateMyType()表達式的結果已經是一個右值。
+2

請注意,問題標記爲C++ 11,因此可能值得一提的是,直到C++ 14才引入'std :: make_unique'。 – user2079303

3

這是正確的用法嗎?

除了std::move是多餘的,是的,這是正確的。這是多餘的,因爲a)複製裸指針,不管它們是左值還是右值,以及b)函數不返回引用,所以返回值已經是右值,因此不需要轉換。

但還有改進的餘地。我特別推薦從工廠函數返回一個唯一指針:

std::unique_ptr<MyType> StaticFuncSomewhereElese::generateMyType() 

這可以防止temp從如果初始化拋出異常泄漏,並使其更難爲工廠的用戶意外泄漏返回指針。