Здравствуйте, remark, Вы писали:
AG>>Как вообще бороться с оверхедом на подсчёт ссылок и стоит ли?
R>*Может* стоить. Стоит ли в конкретном случае — скажет только профайлер.
Профайлер скажет. Вопрос в том, что писать до тех пор, пока профайлер не потребовался, чтобы не пессимизировать преждевременно.
AG>>Кстати, в Delphi для типов, для которых подсчёт ссылок встроен в компилятор, всё просто и без увеличения уровня косвенности:
R>В С++ это тоже тривиально — используй интрузивный умный указатель (boost::intrusive_ptr). Если производительность важна, то неинтрузивный shared_ptr имеет смысл использовать только для прототипирования; а для реального кода — интрузивный (такая же история и с контейнерами — boost::intrusive).
R>При использовании интрузивного подсчёта ссылок в функцию можно передавать обычный указатель на объект, а умный указатель всегда можно из него восстановить при необходимости.
Кстати, похожее возможно с boost::shared_ptr при использовании boost::enable_shared_from_this.
AG>>AG>>procedure P1(S: string; I: IUnknown);
AG>>begin (* неявное увеличение числа сссылок на S и AddRef для I *)
AG>> S := F1(); I := F2(); (* можно *)
AG>>end; (* неявное уменьшение числа сссылок на S и Release для I *)
AG>>
R>Зачем при обычном вызове функции надо менять счётчик 2 раза? Разве вызывающий код может освободить счётчик до возврата из функции?
т.к. переданы I и S "по значению", в самой вызывающей функции этим переменным могут присваиваться другие значения, при присвоении, как обычно счётчик ссылок правой части увеличивается, затем левой уменьшается. Для балланса необходимо это неявное увеличение/уменьшение счётчика ссылок на входе/выходе.
при передаче "по константному значению" возможность присвоение переменной нового значения отсутствует.
наверное, можно было бы в boost::shared_ptr предусмотреть на этот случай класс, который вёл бы себя как shared_ptr без =, reset и swap, который бы не дёргал счётчик ссылок. но у boost::shared_ptr приоритеты — корректность и единообразие, а не оптимальность и настраиваемость.