Подтвердить что ты не робот

Как удалить указатель после возвращения его значения внутри функции

У меня есть эта функция:

char* ReadBlock(fstream& stream, int size)
{
    char* memblock;
    memblock = new char[size];
    stream.read(memblock, size);
    return(memblock);
}

Функция вызывается каждый раз, когда мне приходится читать байты из файла. Я думаю, что он выделяет новую память каждый раз, когда я ее использую, но как я могу освободить память после обработки данных внутри массива? Могу ли я сделать это из-за пределов функции? Обработка данных путем выделения больших блоков дает лучшую производительность, чем выделение и удаление небольших блоков данных?

Большое спасибо за вашу помощь!

4b9b3361

Ответ 1

Динамические массивы освобождаются с помощью delete[]:

char* block = ReadBlock(...);
// ... do stuff
delete[] block;

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

std::vector<char> ReadBlock(std::fstream& stream, int size) {
    std::vector<char> memblock(size);
    stream.read(&memblock[0], size);
    return memblock;
}

Ответ 2

Просто delete[] возвращаемое значение из этой функции, когда вы закончите с ней. Неважно, что вы удаляете его извне. Просто не удаляйте его, прежде чем использовать его.

Ответ 3

Вы можете позвонить:

char * block = ReadBlock(stream, size);
delete [] block;

Но... что много выделения кучи не имеет никакого выигрыша. Рассмотрим этот подход

char *block = new char[size];
while (...) {
  stream.read(block, size);
}
delete [] block;

* Обратите внимание, что если size может быть константой времени компиляции, вы можете просто разместить выделение block.

Ответ 4

Да. Вы можете вызвать delete извне функции. В этом случае, однако, могу ли я предложить использовать std::string, чтобы вам не пришлось беспокоиться об управлении самостоятельно?

Ответ 5

Первое, что нужно отметить: память, выделенная новым и удаленным, полностью глобальна. вещи не удаляются автоматически, когда указатели выходят за пределы области действия или функция выходит из системы. если у вас есть указатель на выделение (например, возвращаемый там указатель), вы можете удалить его когда-либо и где захотите. трюк, просто убедитесь, что другие вещи не удаляют его из-за вас.

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

с другой стороны, возьмите структуру своей функции ReadBlock; если бы у вас не было кода для этого, было бы сложно определить, что именно оно возвращается. это возврат указателя на новую память? если он ожидает, что вы его удалите? удалит ли он его сам? если да, то когда? это даже новый указатель? это просто возврат адреса в какой-то общий статический буфер? если это так, когда буфер станет недействительным (например, перезаписан каким-то другим)

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

скорость мудрая, то есть другое преимущество fsream.read "вы разбираете подход к буферам: вы получаете выбор, когда выделена память. если вы собираетесь" читать данные, обрабатывать, удалять буфер, читать буфер удаления данных данных, ect....", будет намного эффективнее просто выделить один буфер (до максимального размера, который вам понадобится, это будет размер вашего самого большого единственного чтения), и просто используйте это для всего, как предложил Стивен.

Ответ 6

Как использовать статический char * memblock; Он будет инициализирован только один раз, и он не будет каждый раз помещать memblock в новое пространство.