Я хочу передать общий указатель на функцию. Можете ли вы мне помочь?
Конечно, я могу вам помочь. Я предполагаю, что у вас есть некоторое понимание семантики владения в C++. Это правда?
Да, я достаточно комфортно отношусь к теме.
Хорошо.
Хорошо, я могу думать только по двум причинам взять shared_ptr
аргумент:
- Функция хочет разделить право собственности на объект;
- Функция выполняет некоторую операцию, которая работает специально на
shared_ptr
.
Какой вам интересен?
Я ищу общий ответ, поэтому меня действительно интересуют оба. Мне любопытно, что вы имеете в виду в случае № 2.
Примеры таких функций включают в себя std::static_pointer_cast
, пользовательские компараторы или предикаты. Например, если вам нужно найти все уникальные shared_ptr из вектора, вам нужен такой предикат.
Ах, когда функции действительно нужно манипулировать самим смарт-указателем.
Точно.
В этом случае, я думаю, мы должны пройти по ссылке.
Да. И если он не меняет указатель, вы хотите передать его по ссылке const. Вам не нужно копировать, так как вам не нужно делиться собственностью. Это другой сценарий.
Хорошо, получилось. Давайте поговорим о другом сценарии.
Тот, в котором вы делите собственность? ОК. Как вы делитесь собственностью с shared_ptr
?
путем копирования.
Тогда функция должна будет сделать копию shared_ptr
, правильно?
Очевидно. Поэтому я передаю его ссылкой на const и скопирующую локальную переменную?
Нет, это пессимизация. Если он передается по ссылке, у функции не будет выбора, кроме как сделать копию вручную. Если он передается по значению, компилятор выбирает лучший выбор между копией и движением и выполняет его автоматически. Итак, перейдите по значению.
Хороший вопрос. Я должен помнить эту статью «Want Speed? Pass by Value.» чаще.
Подождите, что, если функция хранит shared_ptr
в переменной-члене, например? Разве это не сделает лишнюю копию?
Функция может просто переместить аргумент shared_ptr
в его хранилище. Перемещение shared_ptr
дешево, потому что оно не меняет количество ссылок.
Ах, хорошая идея.
Но я думаю о третьем сценарии: что делать, если вы не хотите манипулировать shared_ptr
или не передавать права собственности?
В этом случае shared_ptr
совершенно не относится к данной функции. Если вы хотите манипулировать указателем, возьмите указатель и позвольте собеседникам выбрать, какую именно семантику владения они хотят.
И должен ли я использовать указатель по ссылке или по значению?
Применяются обычные правила. Умные указатели ничего не меняют.
Передайте по значению, если я собираюсь скопировать, передать по ссылке, если я хочу избежать копирования.
Право.
Хм. Я думаю, вы забыли еще один сценарий. Что делать, если я хочу поделиться собственностью, но только в зависимости от определенного состояния?
Ах, интересный кромка. Я не ожидаю, что это произойдет часто. Но когда это произойдет, вы можете либо пройти по значению, либо проигнорировать копию, если она вам не нужна, или передать по ссылке и сделать копию, если вам это нужно.
Я рискую одной избыточной копией в первом варианте и потеряю потенциальный ход во втором. Разве я не могу есть пирог и тоже?
Если вы находитесь в ситуации, когда это действительно имеет значение, вы можете предоставить две перегрузки, одну из которых ссылается на константу lvalue, а другую - на ссылку rvalue. Один экземпляр, другой движется. Еще одним вариантом является шаблон идеальной пересылки.
Я думаю, что это охватывает все возможные сценарии. Большое спасибо.
'const std :: shared_ptr & arg1' –
Второй способ сломан, первый - идиоматический, если вам действительно нужна ваша функция для совместного владения. Но действительно ли 'DoSomething' действительно нужно поделиться собственностью? Похоже, что вместо этого нужно просто взять ссылку ... – ildjarn
Спасибо Чит, это увеличивает счетчик умных указателей? –