Как я могу написать пользовательское средство удаления для массива, которым управляет unique_ptr? - PullRequest
0 голосов
/ 27 сентября 2019

Я пытаюсь найти способ написать пользовательское средство удаления для массива C, управляемого уникальным_ptr в шаблонном классе C ++.Я целенаправленно пытаюсь заставить утечку памяти класса, заставляя средство удаления ничего не делать.В полном классе некоторые конструкторы выделяют память, а некоторые нет - скорее они используют память в необработанном байтовом буфере, поступающем из потока данных.

Вот что я пробовал:

template <class T> class Matrix
{
    private:
    int _size;
    std::unique_ptr<T[]> _array;

    public:
    Matrix(int size, void* data) : _size(size)
                                 , _array(NULL, [](T[]* p){})
    {
        _array.reset((T*)data);
    }
};

Код не компилируется, сообщение об ошибке:

In file included from /tmp/test/test/test.cpp:9:
/tmp/test/test/Matrix.h:22:55: error: expected ')'
                                 , _array(NULL, [](T[]* p){})
                                                      ^
/tmp/test/test/Matrix.h:22:51: note: to match this '('
                                 , _array(NULL, [](T[]* p){})
                                                  ^
1 error generated.

Ответы [ 2 ]

2 голосов
/ 27 сентября 2019

Прежде всего, всегда создавайте простую настройку для тестирования вещей:

int main() {
    using T = int;

    std::unique_ptr<T[]> _array(NULL, [](T[]* p){});

    return 0;
}

Так что теперь к вашей проблеме:

  • T[]* p недопустимо и должно быть T* p.
  • Лямбда, которую вы передаете в качестве средства удаления, не соответствует std::default_delete<T>, который используется в качестве средства удаления по умолчанию.Поэтому вы должны написать std::unique_ptr<T[],std::function<void(T*)>.
  • И NULL может быть реализован как целочисленный тип, поэтому вы должны использовать вместо него nullptr, иначе gcc не скомпилирует ваш код (так как c ++ 11 вы, как правило, должны использоватьnullptr вместо NULL).

Итак, сложив все вместе, вы получите:

int main() {
    using T = int;

    std::unique_ptr<T[],std::function<void(T[])>> _array(nullptr, [](T* p){});

    return 0;
}
0 голосов
/ 27 сентября 2019

Удалитель является параметром шаблона std::unique_ptr.По умолчанию это std::default_delete, но вы можете указать что-то другое, например

template <typename T>
struct NonDeleter
{
    void operator()(T*) { /* nothing */ }
};

template <typename T>
struct NonDeleter<T[]> : NonDeleter<T> {};

template <class T> class Matrix
{
    private:
    int _size;
    std::unique_ptr<T[], NonDeleter<T[]>> _array;

    public:
    Matrix(int size, void* data) : _size(size)
                                 , _array(static_cast<T*>(data))
    {
    }
};
...