С++ новое выделение массива C, RAII или простой shared_ptr/boost::shared_array

Я изучаю С++, и я снова наткнулся на новую проблему.

Мне нужно выделить массив C для использования библиотекой, но, конечно, безопасным способом. Я уже нашел, что delete[]; в конце метод терпит неудачу с треском.

СТАРЫЙ, не очень хороший:

float *buf;

try {
    buf = new float[daswidth*chans_info.chans*sizeof(float)];
}
catch (std::bad_alloc& ba) // sometimes it throws ! so i do need to stop my execution.
{
    if (DEBUG) tekstasFormat(L"WARNING: bad alloc caught: %s", ba.what());
    return; // skip this iteration then.
}

//... OUR CODE

delete[] buf;

Итак, что я пытался использовать, что отлично работает вместо моего старого выделения и удаления:

float *buf;

std::shared_ptr<float> safe_buf(new float[daswidth*chans_info.chans*sizeof(float)], [](float *p) { delete[] p; });

// OR BOOST EQUIVALENT
boost::shared_array<float> safe_buf(new float[daswidth*chans_info.chans*sizeof(float)]);

buf = safe_buf.get();

И у нас никогда не течет, все довольны. Но как теперь ловить броски new_alloc?!

если я выделю shared_ptr в новой {} области после того, как новая будет уничтожена ... Объясните мне и таким нубам, как я, на будущее немного больше. Как обрабатывать исключения в этом случае?


person Community    schedule 24.12.2014    source источник
comment
Есть ли причина, по которой вы не можете использовать std::vector?   -  person Fantastic Mr Fox    schedule 24.12.2014
comment
std::vector на самом деле содержит T*, который создается при его инициализации. Будут небольшие накладные расходы на проверки и функции, вызываемые при его использовании, но это определенно того стоит.   -  person Fantastic Mr Fox    schedule 24.12.2014
comment
Этот sizeof(float) здесь кажется подозрительным. Не знаю, каков ваш вариант использования, но new float[n*sizeof(float)] выделяет n*sizeof(float) числа с плавающей запятой, а не n*sizeof(float) байта. Просто чтобы вы знали.   -  person milleniumbug    schedule 24.12.2014


Ответы (1)


Предпочитаю std::unique_ptr вместо shared_ptr. Это намного быстрее.

std::unique_ptr<float[]> buf; //construct

try {
    buf.reset(new float[daswidth*chans_info.chans*sizeof(float)]); //give memory
}
catch (std::bad_alloc& ba) // sometimes it throws ! so i do need to stop my execution.
{
    if (DEBUG) tekstasFormat(L"WARNING: bad alloc caught: %s", ba.what());
    return; // skip this iteration then.
}

Однако, как сказал Ben, практически нет причин использовать такой float[]. Вместо этого используйте std::vector. Да, даже для большинства* взаимодействий C.

std::vector<float> buf;

try {
    buf.resize(daswidth*chans_info.chans*sizeof(float)); //give memory
}
catch (std::bad_alloc& ba) // sometimes it throws ! so i do need to stop my execution.
{
    if (DEBUG) tekstasFormat(L"WARNING: bad alloc caught: %s", ba.what());
    return; // skip this iteration then.
}

function_expecting_float_pointer(buf.data()); //use .data() to get the `float*`

* не используйте std::vector, если код C когда-либо «перераспределит» указатель для вас. Вместо этого используйте std::unique_ptr и (1) освободите память, (2) перейдите к C, (3) сбросьте указатель, возвращенный из C.

person Mooing Duck    schedule 24.12.2014
comment
Спасибо, утка, .reset - это то, что мне было нужно. Сброс размера ptr при размещении новых данных - это путь, о котором я не знал. Но один вопрос: массив c не быстрее, чем вектор, при том же использовании, что и массив c? - person ; 24.12.2014
comment
@Arnas: Только одним очень специфическим способом: массивы C не инициализируют данные по умолчанию, и vector попытается инициализировать свои элементы по умолчанию. Правильное и осторожное использование vector сделает их одинаковой скоростью, но если вы не знаете, что делаете, теоретически иногда это может быть немного медленнее. Однако это всегда значительно проще и безопаснее. Используй это. Всегда. - person Mooing Duck; 24.12.2014
comment
Что ж, в моем случае я бы предпочел unique_ptr, так как он инициализирует весь массив с частотой 100 Гц, что совсем не обязательно. - person ; 24.12.2014
comment
@Arnas: (1) Есть несколько причин, по которым вам нужен код для работы на частоте 100 Гц. Обычно 60 Гц - это больше максимум. (2) Единственный раз, когда это было бы ненужным, - это если код C инициализирует массив для вас. Так ли это? - person Mooing Duck; 24.12.2014