Подтвердить что ты не робот

Почему интеллектуальный указатель не вызывает new() для меня в его конструкторе?

Можно ли написать умный указатель, который выделяет сам объект в своем конструкторе - вместо того, чтобы разработчику приходилось звонить new? Другими словами, вместо написания:

std::unique_ptr<myClass> my_ptr(new myClass(arg1, arg2))

... можно написать:

std::smarter_ptr<myClass> my_ptr(arg1, arg2)

Является ли синтаксис языка способным выражать это? Было бы желательно? Отвратительный? Я имею в виду, в частности, защиту от этой ошибки (что я, конечно же, сделал сам):

myFunction(std::unique_ptr<myClass>(new myClass()), std::unique_ptr<myClass>(new myClass()))

..., который рискует протекать в зависимости от того, какой объект будет выделен первым, если произойдет второе распределение и выбрасывается до того, как первый объект будет безопасно помещен в его интеллектуальный указатель. Но мог ли разумный указатель сделать это безопасным?

4b9b3361

Ответ 1

Посмотрите на реализацию make_shared(). Он выделяет новый объект и создает shared_ptr.

Ответ 2

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

Это можно сделать с помощью функции factory, например:

template <typename T, typename... Args>
std::unique_ptr<T> make_unique(Args&&... args) {
    return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
}

Если вы используете std::shared_ptr, вы можете использовать std::make_shared. Это также дает преимущество только в том, что требуется только одно распределение памяти, где std::shared_ptr<T>(new T) потребуется один для объекта, а второй - для общего счетчика ссылок.

Ответ 4

Это по сути та же самая проблема, которая требует std::find и std::find_if. Вы не можете отличить этот ctor от существующих ctors shared_ptr в случае new myClass(arg1). Количество аргументов равно, а arg1 может иметь любой тип.

Поэтому вам нужно другое имя и make_shared