С++ - вопрос с указателем

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

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

Ответ 1

Это можно увидеть двумя способами:

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

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

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

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

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

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

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

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

Ответ 2

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

Отчасти потому, что компилятор часто выполняет команду copy elision на pass-by-value, отрицая стоимость копирования значения, но главным образом потому, что эти два параметра часто ведут себя по-разному.

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

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

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

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

Ответ 3

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

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

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

Ответ 4

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

Ответ 5

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

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