2010-07-11 52 views
7

說我有一個class Tstd::list的:的std ::列表<性病::的unique_ptr <T>>:通過它周圍

std::list<T> l; 

當傳遞入的功能,我會用一個參考:

someFunction(std::list<T> &l) 

傳遞std::listunique_ptr s的最佳方式是什麼?

std::list< std::unique_ptr<T> > l; 

像這樣:

someFunction(std::unique_ptr<T> ptr) 

或者這樣:

someFunction(T* ptr) 

或者這樣:

someFunction(T &ref) 

什麼我會怎麼稱呼它使用std::listback()函數例如?這些都是恕我直言所有「類」的相當,但我敢肯定,我在這裏失去了一些東西。

由於

回答

7

在最佳順序惡化:

  1. someFunction(常量Ť&);
  2. someFunction(T &);
  3. someFunction(const std :: unique_ptr <T> &);
  4. someFunction(std :: unique_ptr <T> &);

第一個是最好的,因爲它不修改對象,它就會與對象,無論工作,你如何分配它(例如,您可以切換沒有問題對於shared_ptr)。

不管你使用的是什麼智能指針,第二個人也會工作;然而,它假定你可以修改對象,並且每當你可以創建一些const的時候,你應該這樣做。

數字3和4都允許被指向的對象被突變;然而,#3不允許修改智能指針,而數字4則不允許修改。兩者都有缺點,他們強制使用unique_ptr,而上面的兩個它將工作,不管智能指針類。

按值傳遞unique_ptr,就像你在其他一些例子中所做的那樣,這不是一個選項; unique_ptr應該是唯一的。如果您正在複製它,請考慮使用shared_ptr。

對於前兩種,如果你調用它)回來的結果(,它看起來像:

someFunction(*(lst.back())); // dereference lst.back() before passing it in. 

對於後兩種,如果你調用它背的resut()它看起來像:

someFunction(lst.back()); // pass the smart pointer, not the object to 
          // which the smart pointer currently points. 
+0

感謝您的深入說明。所以智能指針不需要特殊的語義(除了取消引用)。我知道'const'的東西,但在這種情況下,我需要修改傳入的'T'對象。 – rubenvb 2010-07-11 12:05:43

1

unique_ptr的價值,首先它不會沒有std::move編譯的,如果你做使用std::move將清空您存儲在您的list中的值,您將無法再訪問它。

這是因爲unique_ptr是不可拷貝,它沒有unique_ptr::unique_ptr(const unique_ptr<T>& other),而不是它只有一個移動構造函數(unique_ptr::unique_ptr(unique_ptr<T>&& source))類型的拷貝構造函數。

0

的unique_ptr和含有的unique_ptr可以在標準::列表(和其它容器)中可以使用也類/實例中,只要它們具有構造class_name(class_name &&)定義移動(其中的unique_ptr,當然有)。

當你繞過這些元素,你總是移動(而不是複製),所以你總是在左值使用std ::移動(),如
my_list.push_back(std::move(my_element));
這使得可見你是將元素傳遞(=移動)到列表中,並且在該操作之後my_element是「空」(如空的unique_ptr)。

實施例:

typedef std::unique_ptr<uint8_t[]> data_ptr; 

class data_holder 
{ 
private: 
    int something_about_data; 
    data_ptr data; 
public: 
    data_holder(data_ptr && _data) 
     : data(std::move(_data)) 
    {} 

    // hey compiler, please generate a default move constructor for me 
    // despite of present destructor 
    data_holder(data_holder &&) = default; 

    ~data_holder() 
    { 
     // ... 
    } 

    bool is_empty() const { return ! bool(data); } 
} 

// ... 
{ 
    // ... 
    data_holder the_element(data_ptr(new uint8_t[DATA_SIZE])); 

    // move the_element into the_list 
    the_list.push_back(std::move(the_element)); 
    if (the_element.is_empty()) 
     std::cerr << "data_holder 'the_element' is now empty!" << std::endl; 
    // ... 
} 
相關問題