Здравствуйте, DirtyGarry, Вы писали:
DG>Есть блок данных. В этом блоке нужно найти данные и вернуть указатель на них. Но иногда данных в самом блоке нет, а есть лишь описание (размер, откуда прочитать и т.п.). Родился следующий (условный) прототип функции
DG>BYTE* get_need_data(const BYTE* source_data, DATA_TYPE type, BYTE* need_data_buf)
DG>- source_data [in] — исходные данные
DG>- type [in] — "критерий" поиска нужных данных
DG>- need_data_buf [out] — буфер, содержащий нужные данные, если они не в source_data
DG>Функция всегда возвращает указатель на нужные данные. Если они находятся внутри source_data, то она вернет указатель, которые указывает внутрь source_data. Если нужных данных внутри source_data нет, она сама выделяет буфер need_data_buf, копирует туда данные и возвращает указатель на этот буфер.
DG>Является ли такой подход естественным? Или, например, лучше разделить эту функцию на две: одна находит данные внутри source_data, а другая читает из вне?
Посмотри, как ты будешь работать с такой функцией:
byte * allocated_data = 0;
byte const * needed_data = get_need_data(source, type, &allocated_data);
// process needed_data...
delete [] allocated_data;
Получается не очень красиво. Работаешь с одними данными, а освобождаешь другие. Связь между ними не ясна.
Тут лучше будет возвращать из функции объект, который сам знает, как себя освободить правильно. Например, хорошо подойдет shared_ptr с нужным deleter.
void array_deleter(byte const * arr)
{
delete [] arr;
}
void null_deleter(byte const *) {}
shared_ptr<byte const> get_data(byte const * source, data_type type)
{
if (byte const * found = find_data(source, type)) // нашли?
return shared_ptr<byte const>(found, null_deleter);
// иначе создадим
byte * created = new byte[data_size];
// сразу же отдадим во владение к shared_ptr
shared_ptr<byte const> result(created, array_deleter);
// теперь можно заполнять created...
return result;
}