Есть ли какие-либо недостатки с использованием make shared для создания общего ptr


есть ли какие-либо недостатки с использованием make_shared<T>() вместо shared_ptr<T>(new T).

Boost documentation государства

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

5 51

5 ответов:

Я знаю по крайней мере двух.

  • вы должны контролировать распределение. Не очень большой, но некоторые старые api любят возвращать указатели, которые вы должны удалить.
  • нет пользовательским deleter. Я не знаю, почему это не поддерживается, но это не так. Это означает, что ваши общие указатели должна использовать ваниль делетер.

довольно слабые места. поэтому старайтесь всегда использовать make_shared в.

В дополнение к точкам, представленным @deft_code, еще более слабый:

  • если вы используете weak_ptrs, что жить после того, как все shared_ptrs для данного объекта умерли, то память этого объекта будет жить в памяти вместе с блоком управления до последнего weak_ptr умирает. Другими словами объект уничтожается, но не освобождается до последнего weak_ptr разрушен.

от http://www.codesynthesis.com/~boris/blog/2010/05/24/smart-pointers-in-boost-tr1-cxx-x0/

другим недостатком реализации make_shared () является увеличение размера объектного кода. Благодаря тому, как эта оптимизация реализована, для каждого типа объекта, который вы используете с make_shared (), будет создана дополнительная виртуальная таблица, а также набор виртуальных функций.

кроме того, make_shared не совместим с заводским шаблоном. Это потому, что вызов make_shared внутри вашей заводской функции вызывается код библиотеки, который в свою очередь вызывает new, к которому у него нет доступа,так как он не может вызвать частный конструктор(ы) класса (конструктор(ы) должен быть частным, если вы правильно выполните шаблона "фабрика").

С make shared вы не можете указать, как распределение и освобождение из удерживаемого объекта будет сделано.

когда это необходимо, используйте 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!"));

обратите внимание, что вектор не должен быть проинформирован о распределителе!

для создания пользовательского распределителя, посмотрите здесь https://stackoverflow.com/a/542339/1149664