Любая причина в синтаксической разнице между общими указателями и уникальными указателями с пользовательскими удалителями - PullRequest
0 голосов
/ 24 октября 2018

Хотя общие и уникальные указатели в C ++ 11 допускают определенные пользователем удаления, они имеют заметные синтаксические различия, как показано в приведенном ниже мини-примере:

#include "pch.h"
#include <memory>
class factory
{
public:
    static factory * create() {
        return new factory();
    }
    static void destroy(factory*    fp) noexcept{
        delete fp;
    }
    factory(const factory &) = delete;
    factory& operator= (const factory &) = delete;
private:
    char * p_;
    factory() {
    p_ = new char[100];
    }
    ~factory() {
        delete[] p_;
    }
};

int main()
{
    typedef void(*fp)(factory*);

    auto del = [](factory * p) noexcept {
        factory::destroy(p);
    };

    std::shared_ptr<factory> fsptr1(factory::create(), del);
    std::shared_ptr<factory> fsptr2(factory::create(), del);
    //notice the syntax is different
    std::unique_ptr<factory, fp> ufsptr1(factory::create(), del);
    std::unique_ptr<factory, decltype(del)> ufsptr2(factory::create(), del);

    return 0;
}

Причина этого заключается в том, чтокласс шаблона для общих указателей определен как

template< class T > class shared_ptr;

, а класс шаблона для уникальных указателей определен как

template<class T, class Deleter = std::default_delete<T>> class unique_ptr;

Мой вопрос таков: есть ли какая-либо причина для этого решения о том, чтоСинтаксис двух отличает себя друг от друга?Я наивно думаю, что если шаблонный класс для общих указателей задан как

template< class T, class Deleter = std::default_delete<T>> class shared_ptr;

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

1 Ответ

0 голосов
/ 24 октября 2018

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

См. Здесь: https://github.com/llvm-mirror/libcxx/blob/master/include/memory#L2397

Хранилище - это определенный тип, основанный на типах шаблонов.

Но для std::shared_ptr, у вас нет этого ограничения, у вас уже есть счетчик, вам нужно выделить блок для его хранения.Таким образом, вы можете сделать выбор удаления внутри логики выделения, а не снаружи, на уровне API.

См. Здесь: https://github.com/llvm-mirror/libcxx/blob/master/include/memory#L3592

compressed_pair не находится в самом интеллектуальном указателе,но в выделенном блоке.

...