std::realloc
| Определено в заголовочном файле <cstdlib>
|
||
void* realloc( void* ptr, std::size_t new_size ); |
||
Перераспределяет заданную область памяти. Она должна быть предварительно выделена с помощью std::malloc, std::calloc или std::realloc, но ещё не освобождена с помощью std::free, иначе результат не определён.
Перераспределение может быть выполнено одним из двух способов:
ptr. Содержимое области остаётся неизменным до меньшего из нового и старого размеров. Если область расширена, содержимое новой части массива не определено.new_size байт, копирование области памяти размером, равным или меньшим из нового и старого размеров, и освобождение старого блока.Если памяти недостаточно, старый блок памяти не освобождается и возвращается нулевой указатель.
Если 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);
else
throw std::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
|