C++中用realloc释放小块内存是否高效?相关内存操作疑问
1. 逐字符/逐字符串执行realloc是否合理?
完全不推荐这么做。realloc本身会带来内存管理的额外开销(比如更新内存分配元数据),频繁调用(尤其是逐字符)会把这种开销放大,反而拖慢整体效率。
如果确实需要释放不再使用的内存,建议一次性计算出最终需要保留的总大小,调用一次realloc完成内存调整,而不是逐字符或逐字符串反复调用。比如你要释放最后一个字符,直接计算新大小为n*l - 1,一次调用realloc即可。
2. 缩小内存时realloc会不会触发内存拷贝?
不会。当用realloc缩小内存块时,操作系统只需要修改内存分配的元数据,把原内存块末尾超出新大小的部分标记为可用即可。原内存块中需要保留的数据都在新大小范围内,不需要移动或拷贝,效率远高于扩容时的情况。
3. realloc缩小时是否释放的是指针指向的最后一个字符?
首先纠正你代码里的一个错误:你写的n*l - sizeof(char*)是错的——如果要释放一个char,应该用n*l - sizeof(char)(也就是n*l - 1,因为char的大小固定为1字节),sizeof(char*)是指针的大小(32位系统是4,64位是8),这会导致你多释放很多内存。
回到问题本身:当你用realloc(pStr, new_size)缩小内存时,确实是释放原内存块末尾的部分——原内存块中从new_size位置往后的字节都会被标记为可用。如果你最后一个字符正好在原内存块的末尾,那缩小1字节确实会释放这个字符的空间。
4. 如何移除第一个字符并将剩余内容移至指针地址?
有两种可行方案,各有优劣:
方案一:内存拷贝+
realloc(真正释放内存)
先用memmove把从第二个字符开始的内容拷贝到指针起始位置,再用realloc缩小内存:// 假设原总大小是total_size = n*l size_t new_size = total_size - 1; memmove(pStr, pStr + 1, new_size); pStr = realloc(pStr, new_size);memmove是安全的,即使源地址和目标地址重叠也能正确处理。这种方式会真正释放第一个字符的内存空间,但需要一次拷贝操作。方案二:调整指针(不释放内存,简便但有内存浪费)
直接把指针向后偏移1位,跳过第一个字符:// 注意:必须保存原始malloc返回的指针,否则后续无法正确free char* original_ptr = pStr; pStr += 1; size_t remaining_size = total_size - 1;这种方式不需要拷贝,效率很高,但第一个字符的内存空间并没有被释放,只是你不再使用它。必须保存原始指针,最后调用
free(original_ptr)来释放整个内存块,不能用调整后的pStr去free,否则会导致未定义行为。
内容的提问来源于stack exchange,提问作者Mori

