Инициализируйте std::array с помощью make_shared

Фон

Я пишу драйвер для сетевого протокола и есть функция write(std::shared_ptr<package> package), где package является std::array<buffer_ptr,2> (0=> заголовок, 1=> тело). Для удобства хочу написать функцию write(buffer_ptr body), который автоматически генерирует заголовок и вызывает первую форму write, Для этого я хочу к нам std::make_sharedОднако у меня есть проблемы с инициализацией std::array от make_shared вызов.

Код

typedef std::shared_ptr<std::vector<uint8_t>> buffer_ptr;
typedef std::array<buffer_ptr, 2> package_t;
typedef std::shared_ptr<package_t> package_ptr;

void connection::write(package_ptr package) {
    ... //do stuff
}

void connection::write(buffer_ptr body) {
    buffer_ptr header = buildHeader(body);
    write(std::make_shared<package_t>(???)) //here I want to initialize the array with {header,body}
}

Что я пытался???

(это привело к ошибкам компилятора)

{header, body}
{{header, body}}
std::initializer_list<buffer_ptr>{header, body}

Вопрос:

  1. Есть ли решение, чтобы сделать эту работу, или я должен написать что-то вроде:

    package_ptr package = новый пакет {заголовок, тело}; написать (пакет);

    1.b) Потеряю ли я эффективность, прибегая к package_ptr(new package)? (Я помню, как делить разделяемую память для указателя и экземпляра в одном чанке, чтобы сохранить запросы памяти)

  2. На Cppreference это читает:

    Более того, f(shared_ptr(new int(42)), g()) может привести к утечке памяти, если g выдает исключение. Эта проблема не существует, если используется make_shared.

    Почему память просочилась (могла int(42) быть построенным раньше g называется, и g быть вызванным раньше shared_ptr называется)? И будет ли альтернативный код из 1. страдать от такой потенциальной утечки?

1 ответ

Решение

Первый:

array явно не объявляет конструктор. В частности, он не имеет конструктора, который принимает список инициализатора.

Я думаю, что чистый способ избежать явного new в коде и оставьте его стандартным функциям:

package_t p = {header, body};
write(std::make_shared<package_t>(p));

Код выглядел бы еще лучше, если бы не было ни new ни std::shared_ptr:

package_t p = {header, body};
write(p);

Во-вторых, на Cppreference.com это гласит:

Более того, f(shared_ptr(new int(42)), g()) может привести к утечке памяти, если g выдает исключение. Эта проблема не существует, если используется make_shared.

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

В

f(shared_ptr(new int(42)), g())

new int(42) должен предшествовать shared_ptr() но нет g() и это может вызвать утечку, если g броски.

В

f(make_shared<int>(42), g())

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

Если make_shared называется раньше g и если g броски shared_ptr объект уже был бы создан и его уничтожение гарантировано из-за RAII

Другие вопросы по тегам