假设我有一个std::list
的{{1}}:
class T
将它传递给函数时,我会使用引用:
std::list<T> l;
传递someFunction( std::list<T> &l )
std::list
个unique_ptr
的最佳方法是什么?
std::list< std::unique_ptr<T> > l;
像这样:
someFunction( std::unique_ptr<T> ptr )
或者这个:
someFunction( T* ptr )
或者这个:
someFunction( T &ref )
例如,如何使用std::list
的{{1}}函数调用它?这些是恕我直言,所有“类似”等同,但我确定我在这里遗漏了一些东西。
由于
答案 0 :(得分:8)
为了最好的情况:
第一个是最好的,因为它不会修改它的对象,无论你如何分配它都可以使用它(例如,你可以毫无问题地切换到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.
答案 1 :(得分:1)
不按值传递unique_ptr
,首先如果没有std::move
则无法编译,如果执行则使用{{ 1}}它会清空您std::move
中存储的值,您将无法再访问它。
这是因为list
不可复制,它没有unique_ptr
类型的复制构造函数,而只有一个移动构造函数(unique_ptr::unique_ptr(const unique_ptr<T>& other)
)。
答案 2 :(得分:0)
unique_ptr以及包含unique_ptr的类/实例可以在std :: list(和其他容器)中使用,前提是它们已经定义了移动构造函数 class_name(class_name &&)
(当然,unique_ptr当然,有)。
当你传递这些元素时,你总是移动(而不是复制)它们,所以你总是在lvalues上使用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;
// ...
}