2014-01-25 3 views
54

И unique_ptr, и shared_ptr принимают пользовательский деструктор для вызова объекта, которому они принадлежат. Но в случае с деструктор передается в качестве параметра шаблона класса , тогда как тип настраиваемого деструктора shared_ptr должен быть указан как шаблонный шаблон конструктор.Почему unique_ptr принимает два параметра шаблона, когда shared_ptr принимает только один?

template <class T, class D = default_delete<T>> 
class unique_ptr 
{ 
    unique_ptr(T*, D&); //simplified 
    ... 
}; 

и

template<class T> 
class shared_ptr 
{ 
    template<typename D> 
    shared_ptr(T*, D); //simplified 
    ... 
}; 

Я не могу понять, почему такая разница. Что требует этого?

+0

Я думаю, что причина в том, что как unique_ptr может только построен один раз на один «человека» в то время как shared_ptr могут быть использованы и розданы по всей программе и, следовательно, быть построены с разными аргументами. – Paranaix

+9

Тип 'shared_ptr' - стирает делектор, то есть пользователи' shared_ptr' не должны знать, какой тип имеет делектор. Это имеет временную стоимость (выделение, разыменование), поэтому она не выполняется для 'unique_ptr' (которая является бесплатной). Например. см. http://stackoverflow.com/q/6324694/420683 – dyp

+0

@ dyp: Может быть, это расширит это в ответ, включая краткое руководство по стиранию стилей? Хотя он не отвечает _why_, тот же подход не был выбран для 'unique_ptr' ... Разве это? – Nemo

ответ

47

Если вы предоставите детер в качестве аргумента шаблона (как в unique_ptr), он является частью типа, и вам не нужно хранить что-либо дополнительно в объектах этого типа. Если deleter передается как аргумент конструктора (как в shared_ptr), вам необходимо сохранить его в объекте. Это стоимость дополнительной гибкости, так как вы можете использовать разные удалители для объектов того же типа.

Я думаю, это и есть причина: unique_ptr должен быть очень легким объектом с нулевыми накладными расходами. Хранение удалений с каждым unique_ptr может удвоить их размер. Из-за этого люди вместо этого использовали бы старые добрые указатели, что было бы неправильно.

С другой стороны, shared_ptr не так легковес, так как ему нужно хранить счетчик ссылок, поэтому хранение пользовательского делетера также выглядит как хороший компромисс.

+0

«вы можете использовать разные удалители для объектов того же типа»: Вы имеете в виду, что стандарт хотел, чтобы два разных 'shared_ptr', указывающих на _same object_, были разрушены разными способами? – qdii

+0

* «Если делегат передан как аргумент конструктора (как в shared_ptr), вам необходимо сохранить его в объекте« * Хотя для него может не потребоваться дополнительное хранилище; если делектор без гражданства, он может быть закодирован в типе объекта бухгалтерского учета. – dyp

+2

@qdii - нет, не тот же объект, но другой shared_ptr того же типа. –

Смежные вопросы