Вы начинаете видеть, как невероятно shared_ptr
это :)
Быть безопасным за пределами DLL - это именно то, для чего была разработана shared_ptr
(помимо всего прочего, конечно).
Вопреки тому, что говорили другие, вам даже не нужно передавать пользовательское средство удаления при создании shared_ptr
, так как по умолчанию это уже что-то вроде
template <typename T>
struct default_deleter {
void operator()( T * t ) { delete t; }
};
и
shared_ptr<Foo> foo( new Bar );
эквивалентно
shared_ptr<Foo> foo( new Bar, default_deleter<Bar>() );
(т. Е. Не существует такой вещи, как shared_ptr
без удалителя).
Из-за стирания типа, выполненного для средства удаления, вызываемый delete
будет всегда тем, из библиотеки DLL, в котором был создан экземпляр shared_ptr
, но никогда не из DLL, где последний shared_ptr
выходит из области видимости (т. е. shared_ptr
, вызывающий средство удаления, будет вызывать его через указатель на функцию, помещенную туда исходным shared_ptr
).
Сравните это с auto_ptr
, который встраивает оператор delete
непосредственно в его (встроенный) деструктор, что означает, что используется delete
библиотеки DLL, которая уничтожает auto_ptr
, создание тех же проблем, что и удаление обнаженного указателя.
По той же методике полиморфные классы, которые всегда содержатся в shared_ptr
s, даже не нуждаются в виртуальном деструкторе, потому что средство удаления всегда будет вызывать правильный деструктор, даже когда последний shared_ptr
выйдет из области видимости. один экземпляр для базового класса.