Похоже realloc
не освобождает старую память (в случае успеха или неудачи), пока vector
всегда удаляйте старую память и выделяйте новый блок.
Могу ли я сказать для данных POD, realloc
имеет лучшую производительность, чем vector
?
Например:
int *p = malloc(5 * sizeof(int));
...
int *new_p = (int*) realloc(p, 10 * sizeof(int));
Будет ли старая память p
быть освобожденным здесь?
Realloc может расширить фактическое выделение (если возможно) или может выделить новый фрагмент, скопировать старые значения фрагмента и освободить старый фрагмент. В первом случае он имеет лучшую производительность, но, поскольку вы не знаете заранее, что он собирается делать, вы должны предположить, что указатели на старый блок станут недействительными.
Единственное существенное отличие (игнорирование «синтаксического сахара») состоит в том, что realloc()
может попытаться увеличить размер существующей области; и vector не может этого сделать, и поэтому всегда должен выделять новую область, копировать старые данные в новую область, а затем освобождать старую область.
Исходя из этого, есть 2 случая, когда realloc()
было бы лучше. Первый — когда данные большие (и, следовательно, копирование всего этого обходится дорого), а возможность увеличения размера области позволяет избежать дорогостоящего копирования.
Во втором случае вам просто не хватает (виртуальной) памяти для одновременного существования двух копий. Например, если вы работаете на 32-разрядном компьютере с объемом 2 ГБ, доступным для данных, и у вас есть массив 1,5 ГБ, то вы не можете выделить второй массив 1,5 ГБ (недостаточно места) и должны либо расширить существующую область или потерпеть неудачу.
Обратите внимание, что для обоих этих сценариев (которые относительно редки), оба realloc()
и векторы, вероятно, будут уступать другим подходам. Для простого примера, вместо огромного массива, возможно, вы можете разбить его на связанный список «подмассивов» (например, связанный список из 1000 «подмассивов», каждый из которых равен 1,5 МБ вместо одного массива 1,5 ГиБ). так, что легко создать новый «под-массив» и добавить его в конец списка). Конечно, есть и недостатки других подходов (например, для примера «связанный список подмассивов» итерация становится немного более сложной).