2016-05-21 2 views
3

У вас возникли вопросы при использовании unique_ptr и попытался прочитать исходник, но появилось больше вопросов.Можно ли переустановить тип делетера для unique_ptr?

Параметр шаблона Deleter в unique_ptr<class Tp, class Deleter = default_delete<Tp>> класс, кроме шаблона, так что я интересно, если он использует некоторые приемы, как allocator::rebind (обсуждение найдено here). Но нет, он должен иметь точную перегрузку operator()(pointer).

Поэтому я обратился к источнику НТБ (в Ubuntu 14.04 GCC 4.8) и находим, что вложенная _Pointer класс определяется для некоторых признаков типа, но абсолютно ничего общего с подменой на Deleter типа к чему-то совместимым с типом указателя.

// /usr/include/c++/4.8/bits/unique_ptr.h:112 
class _Pointer 
{ 
    template<typename _Up> 
    static typename _Up::pointer __test(typename _Up::pointer*); 

    template<typename _Up> 
    static _Tp* __test(...); 

    // _Dp is the Deleter type 
    typedef typename remove_reference<_Dp>::type _Del; 
public: 
    typedef decltype(__test<_Del>(0)) type; 
}; 

// /usr/include/c++/4.8/bits/unique_ptr.h:130 
// adopt the pointer type provided by the _Pointer 
typedef typename _Pointer::type pointer; 

Я понятия не имею, что этот класс должен делать, но это, кажется, параметр Tp может быть перекрытым. Чтобы проверить это, я создал некоторые странные коды, подобные этому

struct MyDeleter { 
    // in the deleter type, define the pointer as pointer to int 
    typedef int* pointer; 

    void operator()(pointer p) 
    { 
     delete p; 
    } 
}; 

int main() 
{ 
    // this won't compile! 
    std::unique_ptr<double, MyDeleter> p(new double(0)); 

    // this type is equivalent to std::unique_ptr<int, MyDeleter> 
    std::unique_ptr<double, MyDeleter> p(new int(0)); 
    return 0; 
} 

Я полностью смущен. Кто-нибудь объяснит, что

  • Есть ли какой-либо подход для повторного заполнения типа делетера для unique_ptr?
  • Почему существует такой механизм для переопределения типа указателя? Это указано в стандарте или просто «функции» в реализации gcc?

ответ

1

Правила говорят, что если MyDeleter имеет вложенный тип pointer, тогда используется этот тип. В противном случае std::unique_ptr<double, MyDeleter> будет использовать double*, сформированный из первого параметра.

И указатель, который вы храните, должен соответствовать результирующему типу указателя unique_ptr, в противном случае окончательным удалением будет UB.

Итак, в первом случае std::unique_ptr<double, MyDeleter> p(new double(0)); вы пытаетесь сохранить double*, когда судья ожидает int*. Это никогда не сработает, поэтому хорошо, что компилятор его ловит.

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