std::realloc
来自 cppreference.cn
定义于头文件 <cstdlib> |
||
void* realloc( void* ptr, std::size_t new_size ); |
||
重新分配给定的内存区域(隐式地创建目标区域中的对象)。它必须先前由 std::malloc、std::calloc 或 std::realloc
分配,并且尚未通过 std::free 释放,否则结果是未定义的。
重新分配通过以下方式完成:
a) 如果可能,扩展或收缩 ptr 指向的现有区域。区域的内容保持不变,直到新的和旧的大小中的较小者。如果区域被扩展,则数组新部分的内容是未定义的。
b) 分配大小为 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) // this check is not strictly needed, { std::free(p); // but zero-size realloc is deprecated in 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); // shrink assert(buf1[5] == 'f'); buf1.resize(1024); // grow assert(buf1[5] == 'f'); }
[编辑] 参见
C 文档 关于 realloc
|