Сэнди пишет: «Кажется, что все плюсы и минусы здесь могут быть обобщены на ЛЮБОЙ тип, передаваемый по ссылке, а не просто shared_ptr.»
В некоторой степени верно, но смысл использования shared_ptr состоит в том, чтобы устранить проблемы, связанные с временем жизни объектов, и позволить компилятору справиться с этим за вас. Если вы собираетесь передавать общий указатель по ссылке и разрешать клиентам вашего объекта с подсчетом ссылок вызывать неконстантные методы, которые могут освобождать данные объекта, то использование общего указателя практически бессмысленно.
Я написал «почти» в этом предыдущем предложении, потому что производительность может быть проблемой, и она «может» оправдываться в редких случаях, но я бы также сам избегал этого сценария и сам искал все возможные другие решения по оптимизации, такие как серьезно взглянуть на добавление еще одного уровня косвенности, ленивых вычислений и т. д.
Код, существующий после его автора или даже оставляющий в памяти его автора, который требует неявных предположений о поведении, в частности о поведении объектов, требует четкой, краткой, читаемой документации, и тогда многие клиенты все равно его не прочитают! Простота почти всегда превосходит эффективность, и почти всегда есть другие способы быть эффективными. Если вам действительно нужно передать значения по ссылке, чтобы избежать глубокого копирования конструкторами копирования ваших объектов со счетчиком ссылок (и оператора равенства), то, возможно, вам следует подумать о том, как сделать глубоко скопированные данные указателями со счетчиками ссылок, которые можно скопировал быстро. (Конечно, это только один сценарий разработки, который может не подходить к вашей ситуации).