2016-09-15 173 views
2

從我通過閱讀大部分在這裏查詢時發現的問題來看,在查找唯一指針時彈出,我認爲它應該提供Builder模式描述的行爲。這是unique_ptr的正確用法嗎?

我希望Builder的任何實例(或其子類,因爲它沒有實現任何修改正在構建的對象的過程)擁有正在構建的對象,直到Close返回指向調用者的唯一指針,指出來電者擁有所有權。

Builder.h

template <class type> class Builder 
{ 
public: 
    ~Builder(); 
    unique_ptr<type> Close(); 
protected: 
    Builder(); 
    unique_ptr<type> _uptr; 
}; 

Builder.cpp

template<class type> Builder<type>::Builder() 
{ 
    uptr = make_unique<type>(); 
} 

template<class type> Builder<type>::~Builder() 
{} 

template<class type> unique_ptr<type> Builder<type>::Close() 
{ 
    return uptr; 
} 

我是否懂得按值傳遞的唯一指針的語義?

(包括和爲了簡潔省略/易讀性命名空間)

回答

3

的std ::的unique_ptr不能被複制。相反,爲了正確傳輸基礎指針的所有權,您必須向上移動uptr。

template<class type> unique_ptr<type> Builder<type>::Close() 
{ 
    return std::move(uptr); 
} 
+0

謝謝!這就說得通了。我有一個暗示,我沒有適當地轉移。 – ophilbinbriscoe

1

我是否懂得按值傳遞的唯一指針的語義?

您可以move從的unique_ptr:std::move(this->_uptr)

要與移動慎之又慎無效原始對象的內容。

我已經完成了你的例子來舉例說明威脅:

#include <iostream> 
#include <memory> 

template<typename T> class Builder 
{ 
public: 
    virtual ~Builder() {} 
    std::unique_ptr<T> Close(); 
protected: 
    Builder() {} 
    std::unique_ptr<T> _uptr; 
}; 

class IntBuilder: public Builder<int> 
{ 
public: 
    IntBuilder() : Builder<int>() { 
     this->_uptr = std::unique_ptr<int>(new int); 
    } 
    void setValue(int x) { 
     *(this->_uptr) = x; 
    } 
    std::unique_ptr<int> Close() { 
     return std::move(this->_uptr); 
    } 
}; 

int main() { 
    IntBuilder b; 
    b.setValue(3); 
    auto i = b.Close(); 
    std::cout << *i << std::endl; // OK 
    auto i2 = b.Close(); 
    std::cout << *i2 << std::endl; // Segmentation fault 
} 

雖然this->_uptr是內IntBuilder::Close()移動時,編譯器不會警告你的段錯誤的潛力。


而且我只是用T Builder<T>::Close()代替unique_ptr<T> Builder<T>::Close()作爲類的,後者只是限制靈活性建議。

此外,爲什麼沒有子類管理他們創建的實例。如果他們創建的實例不能被改變,那麼子類需要存儲關於實例的信息,直到其創建(在Close()),並且將不必要地攜帶unique_ptr<T>

以下是我想改變生成器類:

template<typename T> class Builder 
{ 
public: 
    virtual ~Builder() {} 
    T&& Close(); 
protected: 
    Builder() {} 
}; 
+0

我完全意識到我原來的定義是剛性的。其中一部分原因是因爲這最終會成爲課程的更大交付成果的一部分,其分級標準完全側重於我們通過C++理解和使用設計模式。 – ophilbinbriscoe

+0

我也在一個團隊中工作,我們所有人都是新來的語言,所以對於我們更原始的用戶定義類型有嚴格的使用模式,似乎可以消除我的同伴的不明確性。 雖然我看到了這樣做背後的動機。 閱讀此: http://stackoverflow.com/questions/5481539/what-does-t-double-ampersand-mean-in-c11 – ophilbinbriscoe

+0

我仍然有點模糊了究竟什麼時候關閉返回。如果構建器實例是MyClassBuilder,則返回一個包含許多成員的對象實例,其中一些值,其中一些指針,所有權會發生什麼變化?不要通過移動內部來避免複製?或者它是否複製,因爲T的實例不是臨時的? – ophilbinbriscoe