Инициализируйте 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}
Вопрос:
Есть ли решение, чтобы сделать эту работу, или я должен написать что-то вроде:
package_ptr package = новый пакет {заголовок, тело}; написать (пакет);
1.b) Потеряю ли я эффективность, прибегая к
package_ptr(new package)
? (Я помню, как делить разделяемую память для указателя и экземпляра в одном чанке, чтобы сохранить запросы памяти)На 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