繁体   English   中英

std :: list &lt;std :: unique_ptr <T> &gt;:传遍它

[英]std::list< std::unique_ptr<T> >: passing it around

假设我有一个class Tstd::list

std::list<T> l;

将它传递给函数时,我会使用引用:

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

传递一个std::list unique_ptr std::list的最佳方法是什么?

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

像这样:

someFunction( std::unique_ptr<T> ptr )

或这个:

someFunction( T* ptr )

或这个:

someFunction( T &ref )

那么如何使用std::listback()函数调用它呢? 这些是恕我直言所有“类型”相当,但我敢肯定我在这里遗漏了一些东西。

谢谢

为了最好的情况:

  1. someFunction(const T&);
  2. someFunction(T&);
  3. someFunction(const std :: unique_ptr <T>&);
  4. someFunction(标准::的unique_ptr <T>&);

第一个是最好的,因为它不会修改它的对象,无论你如何分配它都可以使用它(例如,你可以毫无问题地切换到shared_ptr)。

无论你使用什么智能指针,第二个也会工作; 但是,它假设您可以修改对象,并且只要您可以创建const,就应该。

数字3和4都允许指向的对象发生变异; 但是,#3不允许修改智能指针,而数字4则允许。 两者都有缺点,它们强制使用unique_ptr,而上面的两个都可以工作,无论智能指针类。

按值传递unique_ptr,就像在其他一些示例中一样,不是一个选项; unique_ptr应该是唯一的。 如果要复制它,请考虑使用shared_ptr。

对于前两个,如果你在back()的结果上调用它,它看起来像:

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

对于后两者,如果你在back()的resut上调用它,它看起来像:

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

及格unique_ptr的价值,首先它不会编译没有std::move ,如果使用std::move将清空您已存储在您的值list ,你将无法访问它了。

这是因为unique_ptr不可复制,它没有unique_ptr::unique_ptr(const unique_ptr<T>& other)类型的复制构造函数unique_ptr::unique_ptr(const unique_ptr<T>& other)而只有一个移动构造函数( unique_ptr::unique_ptr(unique_ptr<T>&& source) )。

unique_ptr以及包含unique_ptr的类/实例可以在std :: list(和其他容器)中使用,前提是它们已经定义了移动构造函数 class_name(class_name &&) (当然,unique_ptr有)。

当你传递这些元素时,你总是移动(而不是复制)它们,所以你总是在左值上使用std :: move(),就像在
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;
    // ...
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM