std::realloc
Определено в заголовочном файле <cstdlib> | ||
void* realloc(void* ptr, std::size_t new_size ); | ||
Перераспределяет заданную область памяти. Она должна быть предварительно выделена с помощью std::malloc, std::calloc или std::realloc
, но ещё не освобождена с помощью std::free, иначе результат не определён.
Перераспределение может быть выполнено одним из двух способов:
Если памяти недостаточно, старый блок памяти не освобождается и возвращается нулевой указатель.
Если ptr является нулевым указателем, поведение такое же, как при вызове std::malloc(new_size)).
Если new_size равно нулю, поведение определяется реализацией: может быть возвращён нулевой указатель (в этом случае старый блок памяти может быть освобождён или не освобождён) или может быть возвращён ненулевой указатель, который возможно нельзя использовать для доступа к памяти. Такое использование устарело (через C DR 400).(начиная с C++20)
Следующие функции должны быть потокобезопасными:
Вызовы этих функций, которые выделяют или освобождают конкретную единицу памяти, происходят в одном общем порядке, и каждый такой вызов освобождения происходит до следующего выделения памяти (если таковое имеется) в этом порядке. | (начиная с C++11) |
Содержание |
[править]Параметры
ptr | — | указатель на область памяти, которую необходимо перераспределить |
new_size | — | новый размер массива |
[править]Возвращаемое значение
В случае успеха возвращает указатель на начало выделенной памяти. Чтобы избежать утечки памяти, возвращаемый указатель должен быть освобождён с помощью std::free() или std::realloc()
. Исходный указатель ptr становится недействительным, и любой доступ к нему является неопределённым поведением (даже если перераспределение было на месте).
В случае ошибки возвращает нулевой указатель. Исходный указатель ptr
остаётся действительным, и его может потребоваться освободить с помощью std::free().
[править]Примечание
Так как перераспределение может вызвать побайтовое копирование (без разницы происходит увеличение или уменьшение выделенной области), необходимо (но недостаточно), чтобы эти объекты имели тип TriviallyCopyable
.
Некоторые нестандартные библиотеки определяют свойства типа "BitwiseMovable" или "Relocatable", описывающие тип, который не имеет:
- внешних ссылок (например, узлы списка или дерева, содержащие ссылку на другой элемент) и
- внутренних ссылок (например, указатель на элемент, который может содержать адрес другого элемента).
К объектам такого типа можно получить доступ после перераспределения их памяти, даже если их конструкторы копирования нетривиальны.
[править]Например
#include <cassert>#include <cstdlib>#include <new> class MallocDynamicBuffer {char* p;public:explicit MallocDynamicBuffer(std::size_t initial =0): p(nullptr){ resize(initial);} ~MallocDynamicBuffer(){std::free(p);}void resize(std::size_t newSize){if(newSize ==0){// эта проверка не является строго необходимой, std::free(p);// но realloc нулевого размера не рекомендуется в C p = nullptr;}else{if(void* mem = std::realloc(p, newSize)) p =static_cast<char*>(mem);elsethrowstd::bad_alloc();}}char& operator[](size_t n){return p[n];}char operator[](size_t n)const{return p[n];}}; int main(){ MallocDynamicBuffer buf1(1024); buf1[5]='f'; buf1.resize(10);// сокращениеassert(buf1[5]=='f'); buf1.resize(1024);// увеличениеassert(buf1[5]=='f');}
[править]Смотрите также
Документация C по realloc |