C ++ - указатель прохождения вопроса - PullRequest
3 голосов
/ 14 июля 2010

Есть ли у кого-нибудь идеи, как передать boost::shared_ptr - по значению или по ссылке.

На моей платформе (32 бита) sizeof(shared_ptr) равно 8 байтам, и, похоже, я должен передать их по ссылке, но, может быть, у кого-то есть другое мнение / есть профиль / что-то подобное?

Ответы [ 5 ]

5 голосов
/ 14 июля 2010

В C ++, как правило, плохая идея выбирать, передавать ли по значению или по ссылке в зависимости от размера объекта.

Отчасти потому, что компилятор часто выполняет удаление копии при передаче по значению, отрицаяСтоимость копирования значения, но в основном потому, что эти два параметра часто ведут себя по-разному .

Так что выберите параметр, который из числа лучших показывает, что вам нужно сделать.

С помощью shared_ptr, вся причина его существования в том, что он может быть скопирован, так что несколько объектов могут совместно владеть указанным объектом.Если вы никогда не передадите shared_ptr по значению, вы можете задуматься, почему это shared_ptr вообще.scoped_ptr может быть более эффективным решением, чем тогда.

Очевидно, это не значит, что вы должны всегда передавать shared_ptr по значению.Именно эта передача по значению является распространенным случаем для них.

Если вам нужно, чтобы вызывающий и вызываемый лица имели совместное владение, передавайте по значению.Если вы не хотите, чтобы вызываемый пользователь принял какое-либо право собственности, перейдите по ссылке.

2 голосов
/ 14 июля 2010

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

Конечно, это не всегда возможно, например, в контейнерах или в членских переменных, которые должны содержать собственную ссылку.

И, как сказал другой отвечающий, подавляющее большинство любых издержек в C ++ находится в con / destructor, а не в необработанных битах и ​​байтах. Это верно и для shared_ptr.

1 голос
/ 14 июля 2010

Вы можете увидеть это двумя способами:

  • a boost::shared_ptr является объектом (и должен быть передан const &).

  • a boost::shared_ptr моделирует указатель и должен рассматриваться как указатель.

Оба они действительны, а второй вариант повлечет за собой затраты на создание и уничтожение дополнительного экземпляра.(что не должно быть большой проблемой, если вы не пишете код, критичный для производительности).

В двух случаях следует передать по значению:

  • когда вы не уверены, что тип указателя останется прежним.То есть, если вы собираетесь заменить shared_ptr<T> на T* в своей кодовой базе где-то в будущем, имеет смысл написать typedef shared_ptr<T> TPtr; и определить ваши функции как void yourfunction(TPtr value)

    В этом случаекогда вы изменяете тип указателя, вам нужно будет изменить только строку typedef.

  • , когда вы делите указатель между двумя модулями с разным временем жизни.В этом случае вам необходимо убедиться, что у вас есть два экземпляра интеллектуального указателя, и что оба увеличивают счетчик ссылок указателя.

В других случаях это вопрос предпочтения(если вы не пишете код, критичный к производительности, в этом случае применяются другие правила).

1 голос
/ 14 июля 2010

Я считаю, что суть shared_ptr заключается в том, что он является объектом и должен передаваться по значению. Насколько я помню, он автоматически обрабатывает подсчет ссылок, используя ctor & dtor, поэтому он знает, когда освобождать указатель.

Всякий раз, когда я использовал его, я передавал его по значению.

1 голос
/ 14 июля 2010

Я бы передал shared_ptr по ссылке на const. Если вы передадите его по значению, счетчик использования будет увеличен при входе в функцию и уменьшен при выходе из нее, что не требует дополнительных затрат.

...