Как объединить std :: make_shared и new (std :: nothrow)

В новой версии C ++ есть возможность вернуть нулевой указатель, а не выдавать исключение bad_alloc в случае неудачного размещения.

Foo * pf = new(std::nothrow) Foo(1, 2, 3);

(Да, я понимаю, что это только препятствует тому, чтобы новый бросал bad_alloc; это не мешает конструктору Foo генерировать исключение.)

Если вы хотите использовать совместно используемый указатель вместо необработанного указателя, вы, как правило, должны использовать make_shared, так как он хорошо разбирается в распределении блока управления.

auto pf = std::make_shared<Foo>(1, 2, 3);

make_shared инкапсулирует новый, что делает невозможным (?) выбрать версию nothrow. Так что, похоже, вам нужно отказаться от make_shared и явно вызывать new.

std::shared_ptr<Foo> pf(new(std::nothrow) Foo(1, 2, 3));

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

Есть ли способ получить преимущество make_shared для одиночного размещения при сохранении возможности просто получить нулевой указатель вместо исключения bad_alloc при выделении пространства для Foo?

13

Решение

Это выглядит как allocate_shared, передавая распределитель, который использует nothrow новый должен сделать свое дело для вас.

7

Другие решения

Просто создайте собственный nake_foo и поймайте исключение:

#include <memory>

struct Foo {
Foo(int, int, int) { throw std::bad_alloc(); }
};

std::shared_ptr<Foo> make_foo(int a, int b, int c) {
try { return std::make_shared<Foo>(a, b, c); }
catch (const std::bad_alloc&) { return std::shared_ptr<Foo>(); }
}
1

По вопросам рекламы [email protected]