Как передать умные указатели в функции?

При передаче объектов в функции применяются ли к интеллектуальным указателям те же правила, что и к другим объектам, содержащим динамическую память?

Когда я прохожу, например, std::vector<std::string> в функцию я всегда рассматриваю следующие варианты:

  1. Я собираюсь изменить состояние векторного объекта, но я не делайте если эти изменения будут отражены после завершения функции, AKA сделает копию.

    void function(std::vector<std::string> vec);
    
  2. Я собираюсь изменить состояние векторного объекта, и я делать Если эти изменения будут отражены после завершения функции, AKA сделает ссылку.

    void function(std::vector<std::string> & vec);
    
  3. Этот объект довольно большой, поэтому лучше передать ссылку, но скажите компилятору, чтобы он не менялся.

    void function(std::vector<std::string> const& vec);
    

Теперь это та же логика с умными указателями? И когда я должен рассмотреть семантику перемещения? Некоторые рекомендации о том, как я должен передавать умные указатели, это то, что я хочу больше всего

13

Решение

Умные указатели имеют семантика указателя, не значение семантики (ну, не так, как вы это имеете в виду). Думать о shared_ptr<T> как T*; относиться к нему как таковому (ну, кроме подсчета ссылок и автоматического удаления). Копирование умного указателя не копирует объект, на который он указывает, как копирование T* не копирует T это указывает на.

Вы не можете скопировать unique_ptr совсем. Весь смысл в том, что класс не могу быть скопированным; если бы мог, то не был бы уникальный (т.е. единственное число) указатель на объект. Вы должны либо передать его по какой-либо форме ссылки или перемещение Это.

Умные указатели это все о владение на что они указывают. Кому принадлежит эта память и кто будет нести ответственность за ее удаление. unique_ptr представляет уникальное владение: этой памяти принадлежит только один фрагмент кода. Вы можете передать право собственности (через move), но при этом вы потерять владение памятью. shared_ptr представляет совместную собственность.

Во всех случаях использование умного указателя в списке параметров представляет передача права собственности. Поэтому, если функция принимает умный указатель, то она собирается Запрос владение этим объектом. Если функция не должна вступать во владение, тогда она вообще не должна брать умный указатель; использовать ссылку (T&) или если вам нужна обнуляемость, указатель, но никогда не храните его.

Если вы передаете кому-то unique_ptr, ты давая им право собственности. Это означает, что по характеру уникальной собственности вы проигрыш владение памятью. Таким образом, практически нет причин когда-либо сдавать unique_ptr ничем, кроме стоимости.

Точно так же, если вы хотите поделиться правами собственности на некоторый объект, вы передаете shared_ptr, Делаете ли вы это по ссылке или по значению, зависит от вас. Поскольку вы разделяете право собственности, он все равно сделает копию (предположительно), так что вы могли бы также взять ее по значению. Функция может использовать std::move переместить его в учеников или тому подобное.

18

Другие решения

Если функция не собирается изменять или копировать указатель, просто используйте тупой указатель. Умные указатели используются для управления временем жизни объекта, но функция не собирается изменять время жизни, поэтому ей не нужен умный указатель, а использование немого указателя дает вам некоторую гибкость в типе, используемом вызывающей стороной.

void function(std::string * ptr);

function(my_unique_ptr.get());
function(my_shared_ptr.get());
function(my_dumb_ptr);

unique_ptr не может быть скопировано, поэтому, если вы должны передать его, вы должны передать ссылку.

4

Умный указатель — это объект, который ссылается на другой объект и управляет его временем жизни.

Передача умного указателя требует соблюдения семантики, которую поддерживает умный пуитнер:

  • Проходя как const smartptr<T>& всегда работает (и вы не можете изменить указатель, но можете изменить состояние того, на что он указывает).
  • Проходя как smartptr<T>& всегда работает (и вы можете изменить указатель).
  • Проходя как smartptr<T> (копией) работает только если SmartPtr копируемый Работает с std::shared_ptr, но не с std::unique_ptr, если вы не «переместите» его по вызову, как в func(atd::move(myptr))тем самым сводя на нет myptr, перемещая указатель на переданный параметр. (Обратите внимание, что движение неявно, если myptr временно).
  • Проходя как smartptr<T>&& (при перемещении) навязывает указатель для перемещения по вызову, заставляя вас явно использовать std::move (но требует «переместить», чтобы иметь смысл для конкретного указателя).
4
По вопросам рекламы [email protected]