Есть ли причина не использовать std:: make_shared при построении объектов?
Я не могу думать о ситуации, когда
std::shared_ptr<Object> obj(new Object("foo", 1));
было бы предпочтительнее
auto obj = std::make_shared<Object>("foo", 1);
Последнее всегда приводит к лучшей локальности и уменьшает фрагментацию памяти. Есть ли ситуация, когда вы предпочитаете (или должны быть вынуждены) использовать первую форму, за исключением взаимодействия с кодом, возвращающим исходные указатели?
Ответы
Ответ 1
Последнее всегда приводит к лучшей локальности и уменьшает фрагментацию памяти.
Не всегда. Реализация рекомендуется использовать единое распределение для подсчитанного объекта ссылки и счетчика ссылок, но это не требуется для этого.
Почему вы не хотите использовать std::make_shared
? Рассмотрим случай, когда у вас есть большой динамически выделенный объект, которым вы хотите принадлежать std::shared_ptr
, и вы знаете, что будут слабые ссылки на этот объект, которые могут пережить сильные ссылки на объект (возможно, есть много слабых ссылок и только одна или две недолговечные сильные ссылки).
В этом случае std::make_shared
будет плохим выбором, предполагая, что он выделяет один блок, которому принадлежит как объект, так и счетчик ссылок: выделенный блок (который большой, помнит) не может быть уничтожен, пока не будет сильного или слабые ссылки, оставленные объекту.
Если бы вы динамически выделили объект самостоятельно и передали указатель на конструктор std::shared_ptr
, память, занятая объектом, могла быть выпущена, как только остались сильные ссылки, даже если все еще есть слабые ссылки.
Ответ 2
Если вы создаете объект, который будет иметь несколько сущностей, совместно используемых в течение жизни объекта, тогда да, вы предпочитаете использовать std:: make_shared, где это возможно. В некоторых местах это может быть невозможно, если вы получаете указатель от кого-то другого; например, factory может возвращать необработанный указатель или std:: unique_ptr, которые вы хотите сохранить в shared_ptr, тем самым предотвращая использование make_shared.
Вопрос в названии немного отличается; есть много причин, по которым вы, возможно, не захотите использовать shared_ptr для своих объектов вообще. Вы должны использовать shared_ptr, если время жизни фактически разделяется несколькими объектами. В противном случае предпочитайте стеки, выделяющие объект, или используя unique_ptr.
Ответ 3
Современные IDE имеют функцию "Найти использование". Если вы используете std::make_shared
для построения объекта, при поиске мест, где вызывается конструктор этого объекта, среда IDE не будет отображать места, где используется std::make_shared
.