2010-07-11 54 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; 
    // ... 
} 
相关问题