Как удалить указатель после возврата его значения внутри функции - PullRequest
29 голосов
/ 30 июня 2010

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

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

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

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

Ответы [ 6 ]

15 голосов
/ 30 июня 2010

Динамические массивы освобождаются с помощью 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;
}
5 голосов
/ 30 июня 2010

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

4 голосов
/ 30 июня 2010

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

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

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

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

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

1 голос
/ 30 июня 2010

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

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

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

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

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

1 голос
/ 30 июня 2010

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

0 голосов
/ 19 ноября 2015

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...