11

假设我有一个std::listofclass T的:

std::list<T> l;

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

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

std::list传递 s 的(元素)的最佳方式是unique_ptr什么?

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

像这样:

someFunction( std::unique_ptr<T> ptr )

或这个:

someFunction( T* ptr )

或这个:

someFunction( T &ref )

例如,我将如何使用std::list'back()函数调用它?恕我直言,这些都是“某种”等价的,但我确定我在这里遗漏了一些东西。

谢谢

4

3 回答 3

9

按从好到坏的顺序:

  1. someFunction(const T&);
  2. 一些函数(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。

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

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

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

someFunction(lst.back()); // pass the smart pointer, not the object to
                          // which the smart pointer currently points.
于 2010-07-11T11:55:11.060 回答
2

不要按值传递,首先它不会在没有 a 的情况下编译如果你使用它,它将清空你存储在你的值,你将无法再访问它。unique_ptrstd::movestd::movelist

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

于 2010-07-11T12:33:07.967 回答
0

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;
    // ...
}
于 2013-10-12T09:15:16.983 回答