Разница между make_unique и make_unique с reference_wrapper в c ++ - PullRequest
0 голосов
/ 28 марта 2019
struct Foo{};

В чем разница между std::make_unique<Foo> и std::make_unique<std::reference_wrapper<Foo>>?

Ответы [ 3 ]

2 голосов
/ 28 марта 2019

std::make_unique<Foo> создает Foo с динамическим сроком хранения из любых переданных аргументов. std::make_unique<Foo>(args...) является допустимым выражением тогда и только тогда, когда Foo(args...) также допустимо.

std::make_unique<std::reference_wrapper<Foo>> создает std::reference_wrapper<Foo> с динамической продолжительностью хранения, либо из другого std::reference_wrapper<Foo>, либо из чего-то, что будет привязано к Foo &, но не Foo &&. Он не создает никаких дополнительных Foo s, вам нужен хотя бы один Foo, чтобы уже где-то существовать.

Я не могу придумать вескую причину для использования std::unique_ptr<std::reference_wrapper<Foo>> вместо gsl::observer<Foo> (он же Foo *), std::reference_wrapper<Foo> или std::unique_ptr<Foo>, в зависимости от того, что вы пытаетесь сделать.

2 голосов
/ 28 марта 2019

std::make_unique<Foo>

возвращает

std::unique_ptr<Foo>.


std::make_unique<std::reference_wrapper<Foo>>

возвращает

std::unique_ptr<std::reference_wrapper<Foo>>.


std::reference_wrapper - это не принадлежащая оболочка поверх простого указателя. Что приводит к std::unique_ptr владению std::reference_wrapper<Foo>, которому не принадлежит Foo, к которому это относится.

std::unique_ptr<std::reference_wrapper<Foo>> эквивалентно std::unque_ptr<Foo*>, где Foo* уничтожается, а Foo - нет. С ним легко вызвать утечки памяти, победив цель std::unique_ptr.

1 голос
/ 28 марта 2019

std::make_unique<std::reference_wrapper<Foo>> возвращает интеллектуальный указатель на ссылку на Foo.

Ссылка на Foo размещается в куче.

Фактически Foo не создано.

По той же причине это не скомпилируется:

auto x = std::make_unique<std::reference_wrapper<Foo>>();

Результат:

error: 'std::reference_wrapper<Foo>': no appropriate default constructor available

Единственный способ заставить его работать, это заставить его обратиться к некоторому ранее существовавшему Foo:

Foo foo;
auto x = std::make_unique<std::reference_wrapper<Foo>>(foo);

Не могу придумать правильный вариант использования для этого.

...