在全局运算符new返回的指针上使用realloc

Mic*_*ser 2 c++ dynamic-memory-allocation

realloc在C++中没有; 当然,你总是可以分配一个新块new,将旧块复制到新块,释放旧块delete.

问题是realloc通常比这更快 - 当内存块"就地"重新调整大小时会发生这种情况 - 即返回值realloc恰好与参数指针值相同; 这也避免了将内存从旧块复制到新块.

标准说什么 - 是否允许将全局new运算符返回的指针传递给realloc?(glibc中都newmalloc使用相同的分配,所以不应该在这里是一个实际问题).C++标准对此主题有什么要说的吗?

(当前glibc标准C++库不执行realloc,即使在向量中 - 因为一旦分配了一个对象,运行时就无法在旧内存块上调用析构函数并在新块上调用new new - 如果内存块被移动了realloc.如果标准库有一个realloc不能将参数块移动到新位置的就地,那会更简单)

编辑:

实际上一些内存分配器具有就地realloc功能; 这些当然是非标准的.

  • jemalloc有一个rallocm带有标志的APIALLOCM_NO_MOVE
  • dlmalloc(Doug Lea malloc)有一个名为的APIdlrealloc_in_place

如果您使用jemalloc或dlmalloc为全球运营商newdelete,那么你可以使用这些非标准的功能,在就地尝试了一个向量类realloc之前它移动malloc与复制.或者可以请求C++标准委员会在标准中添加全局非移动重新分配方法.

编辑:

或者你可以做一个通过malloc/ realloc/ 来完成内存管理的向量类free,但是如果元素类型是普通的旧数据(例如,如果std::is_pod在向量所持有的类型上返回true),则只能实例化此实现.

sky*_*ing 6

不,你不能混合free/ realloc与内置new.

您正在寻找的大部分功能都可以使用std::vector.保证(AFAIK)矢量中的对象是连续存储的(就像旧样式数组一样),您可以获得指向存储的指针,并且可以以标准定义的方式调整数组的大小.似乎唯一缺乏的是提供自己的存储的可能性(即拥有T*并获得std::vector<T>该存储).

如果你真的需要(首先检查下面的缺点),你可能会做的是替换默认的实现newdelete使用mallocfree:

void* operator new(size_t n)
{
    return malloc(n);
}

void operator delete(void* p)
{
     free(p);
}
Run Code Online (Sandbox Code Playgroud)

在这之后,你可以使用realloc指针得到的new.

正如Michael Walz所指出的那样,如果要分配的对象需要初始化,则需要注意.如果只是复制内存而无法移动对象,那就更糟糕了(realloc如果它无法在适当的位置调整块的大小).这意味着除了愚蠢的结构之外,它在其他任何东西上都是无用的(即使这样,你最终会得到像C语义一样的未初始化数据 - 甚至不是零初始化).

此外malloc,freerealloc没有很好地与C++更强的打字.这个

  • 考虑一下:`myclass*p = new myclass [10];`.`myclass`构造函数将被调用10次,对于数组的每个元素都会调用一次.现在你有`p =(myclass*)realloc(15*sizeof(myclass));`.你认为`myclass`构造函数会被调用5次吗?当然不是,`p [10]`到`p [14]`只会包含垃圾指针. (3认同)
  • 无论你如何切割,切片或切块,这都是一个坏主意.如果您正在考虑这种方法,**现在停止**. (2认同)