Скажите, что у меня есть a std::list
из class T
:
std::list<T> l;
При передаче его в функции я использовал бы ссылку:
someFunction( std::list<T> &l )
Что лучший способ состоит в том, чтобы раздать (элементы) a std::list
из unique_ptr
s?
std::list< std::unique_ptr<T> > l;
Как это:
someFunction( std::unique_ptr<T> ptr )
Или это:
someFunction( T* ptr )
Или это:
someFunction( T &ref )
И что, как был бы, я называю его с помощью std::list
back()
функция, например? Они - по моему скромному мнению, все "довольно" эквивалентные, но я уверен, что пропускаю что-то здесь.
Спасибо
От лучшего к худшему:
Первый вариант лучше всего, потому что он не изменяет объект, и он будет работать с объектом независимо от того, как вы его распределили (например, вы можете без проблем переключиться на 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.
Не не передавайте unique_ptr
по значению, во-первых, он не будет компилироваться без std :: move
, а если вы сделаете используйте std :: move
, он очистит значение, которое вы сохранили в своем списке
, и вы больше не сможете получить к нему доступ.
Это связано с тем, что unique_ptr
не копируется, у него нет конструктора копирования типа unique_ptr :: unique_ptr (const unique_ptr
вместо этого он имеет только конструктор перемещения ( unique_ptr :: unique_ptr (unique_ptr
).