Есть ли недостатки с использованием make_shared для создания shared_ptr
Есть ли недостатки с использованием make_shared<T>()
вместо использования shared_ptr<T>(new T)
.
Boost documentation утверждает
Повторялись запросы от пользователей для функции factory, которая создает объект определенного типа и возвращает shared_ptr к нему. Кроме удобство и стиль, такая функция также является безопасным исключением и значительно быстрее, потому что он может использовать единое распределение как для объект и соответствующий ему контроль блока, устраняя значительный часть конструкции shared_ptr накладные расходы. Это устраняет один из жалобы о большой эффективности shared_ptr.
Ответы
Ответ 1
Я знаю как минимум два.
- Вы должны контролировать распределение. Не очень большой, но некоторые старые api любят возвращать указатели, которые вы должны удалить.
- Никакой пользовательский дебетер. Я не знаю, почему это не поддерживается, но это не так. Это означает, что ваши общие указатели должны использовать детонатор ванили.
Довольно слабые места. поэтому старайтесь всегда использовать make_shared.
Ответ 2
В дополнение к точкам, представленным @deft_code, еще более слабый:
- Если вы используете
weak_ptr
, которые живут после того, как все shared_ptr
к данному объекту умерли, тогда память этого объекта будет находиться в памяти вместе с блоком управления до тех пор, пока не исчезнет последний слабый_ptr. Другими словами, объект уничтожается, но не освобождается до тех пор, пока не будет уничтожен последний weak_ptr
.
Ответ 3
От http://www.codesynthesis.com/~boris/blog/2010/05/24/smart-pointers-in-boost-tr1-cxx-x0/
Другим недостатком реализации make_shared() является увеличение размера объектного кода. Благодаря тому, как эта оптимизация будет реализована, будет создана дополнительная виртуальная таблица, а также набор виртуальных функций для каждого типа объекта, который вы используете с make_shared().
Ответ 4
Кроме того, make_shared
не совместим с шаблоном factory. Это связано с тем, что вызов make_shared
внутри вашей функции factory вызывает код библиотеки, который, в свою очередь, вызывает new
, к которому у него нет доступа, , поскольку он не может вызвать частный конструктор класса (s ) (конструктор должен быть закрытым, если вы правильно следуете шаблону factory).
Ответ 5
При использовании совместного использования вы не можете указать, как будет выполняться распределение и освобождение удерживаемого объекта.
Если это необходимо, используйте std::allocate_shared<T>
вместо этого:
std::vector<std::shared_ptr<std::string>> avec;
std::allocator<std::string> aAllocator;
avec.push_back(std::allocate_shared<std::string>(aAllocator,"hi there!"));
Обратите внимание, что вектор не должен быть проинформирован о распределителе!
Для создания настраиваемого распределителя посмотрите здесь fooobar.com/info/105492/...