сделать уникальный и совершенный пересылка
почему нет std::make_unique
шаблон функции в стандартной библиотеке C++11? Я нахожу
std::unique_ptr<SomeUserDefinedType> p(new SomeUserDefinedType(1, 2, 3));
немного многословен. Разве не было бы намного приятнее следующее?
auto p = std::make_unique<SomeUserDefinedType>(1, 2, 3);
это скрывает new
красиво и только один раз упоминает о типа.
в любом случае, вот моя попытка реализации make_unique
:
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::forward
материал для компиляции, но я не уверен, если это правильно. Так ли это? Что именно делает std::forward<Args>(args)...
в смысле? Что компилятор делает из этого?
6 ответов:
Херб Саттер, председатель комитета по стандартизации C++, пишет на своем блог:
что C++11 не включает
make_unique
Это отчасти недосмотр, и он почти наверняка будет добавлен в будущем.Он также дает реализацию, которая идентична той, которую дает OP.
Edit:
std::make_unique
теперь является частью C++14.
приятно, но Stephan T. Lavavej (более известный как STL) имеет лучшее решение для
make_unique
, который работает правильно для версии массива.#include <memory> #include <type_traits> #include <utility> template <typename T, typename... Args> std::unique_ptr<T> make_unique_helper(std::false_type, Args&&... args) { return std::unique_ptr<T>(new T(std::forward<Args>(args)...)); } template <typename T, typename... Args> std::unique_ptr<T> make_unique_helper(std::true_type, Args&&... args) { static_assert(std::extent<T>::value == 0, "make_unique<T[N]>() is forbidden, please use make_unique<T[]>()."); typedef typename std::remove_extent<T>::type U; return std::unique_ptr<T>(new U[sizeof...(Args)]{std::forward<Args>(args)...}); } template <typename T, typename... Args> std::unique_ptr<T> make_unique(Args&&... args) { return make_unique_helper<T>(std::is_array<T>(), std::forward<Args>(args)...); }
Это можно увидеть на его ядро C++ 6 видео.
обновленная версия STL версии make_unique теперь доступна как N3656. Эта версия был принят в проект C++14.
std::make_shared
Это не просто стенография дляstd::shared_ptr<Type> ptr(new Type(...));
. Он делает то, что вы не может обойтись без него.чтобы сделать свою работу,
std::shared_ptr
необходимо выделить блок отслеживания в дополнение к хранению для фактического указателя. Однако, потому чтоstd::make_shared
выделяет фактический объект, возможно, чтоstd::make_shared
выделяет оба объекта и блок отслеживания в том же блоке памяти.пока
std::shared_ptr<Type> ptr = new Type(...);
будет два выделение памяти (один дляnew
, одно вstd::shared_ptr
блок слежения),std::make_shared<Type>(...)
выделяет один блок памяти.что важно для многих потенциальных пользователей
std::shared_ptr
. Единственное, что astd::make_unique
хотел сделать, это быть немного более удобным. И ничего больше.
хотя ничто не мешает вам написать свой собственный помощник, я считаю, что основная причина предоставления
make_shared<T>
в библиотеке это то, что он фактически создает другой внутренний тип общего указателя, чемshared_ptr<T>(new T)
, который по-разному выделяется, и нет никакого способа достичь этого без выделенного помощника.
кодустранение: это на самом деле не так: имея вызов функции, чтобы обернутьmake_unique
фантик с другой стороны-это просто синтаксический сахар вокругnew
выражение, так что хотя это может выглядеть приятным для глаз, это не принесите что-нибудьnew
к столу.new
выражение обеспечивает безопасность исключений, например в случае, когда вы вызываете функциюvoid f(std::unique_ptr<A> &&, std::unique_ptr<B> &&)
. Имея два сырыхnew
s, которые не связаны друг с другом, означает, что если одно новое выражение не выполняется с исключением, другое может привести к утечке ресурсов. Что касается того, почему нетmake_unique
в стандарте: это было просто забыто. (Это происходит иногда. Там также нет глобальногоstd::cbegin
в стандарте, хотя должен быть один.)также обратите внимание, что
unique_ptr
принимает второй параметр шаблона, который вы должны каким-то образом учитывать; это отличается отshared_ptr
, который использует тип стирания для магазине пользовательские deleters, не делая их частью типа.
В C++11
...
используется (в коде шаблона) для "аддон" тоже.требование заключается в том, что вы используете его в качестве суффикса выражения, содержащего нерасширенный пакет параметров, и он просто применит выражение к каждому из элементов пакета.
например, основываясь на вашем примере:
std::forward<Args>(args)... -> std::forward<int>(1), std::forward<int>(2), std::forward<int>(3) std::forward<Args...>(args...) -> std::forward<int, int, int>(1,2,3)
последнее неверно, я думаю.
кроме того, пакет аргументов не может быть передан в функцию unexpanded. Я не уверен насчет пакета параметров шаблона.
вдохновленный реализацией Stephan T. Lavavej, я подумал, что было бы неплохо иметь make_unique, который поддерживает экстенты массива,это на github и я хотел бы получить комментарии об этом. Это позволяет сделать следующее:
// create unique_ptr to an array of 100 integers auto a = make_unique<int[100]>(); // create a unique_ptr to an array of 100 integers and // set the first three elements to 1,2,3 auto b = make_unique<int[100]>(1,2,3);