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

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

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

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

Большое спасибо за Вашу справку!

30
задан Emer 30 June 2010 в 00:54
поделиться

5 ответов

Динамические массивы освобождаются с помощью 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;
}
15
ответ дан 28 November 2019 в 00:23
поделиться

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

1
ответ дан 28 November 2019 в 00:23
поделиться

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

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

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

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

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

1
ответ дан 28 November 2019 в 00:23
поделиться

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

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

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

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

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

4
ответ дан 28 November 2019 в 00:23
поделиться

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

5
ответ дан 28 November 2019 в 00:23
поделиться
Другие вопросы по тегам:

Похожие вопросы: