关于C++中New的疑惑!

北京的雾霾天 2009-10-10 02:43:19
加精
C++中的New自然是有它独特的好处,然而我却为如下的问题感到疑惑。
比如我用new动态声明了一个长度为10的数组,可是后来发现长度不够用了,我要改成20个,那么我怎么做呢?
1:重新new一个20个长度的数组,把数据Copy到这个数组并把原来的数组内存释放。
2:使用vector之类的C++内置数组类型。
3: ...
4:一开始就声明一个足够大的内存。

我不太清楚vector的内存分配情况,但我知道用new分配的第一个数组空间不会用到第二个数组,相当于第一个数组内存空间被“碎片化”了,因为它可能在程序退出之前永远不会再用到。

然而上面的第三种情况似乎是C语言中的realloc函数,至少这个函数在把10个长度的数组有可能被用到后来的20个长度中。因为这个函数是在原来内存的后面扩展空间。可是realloc函数是与malloc配对使用的,这里又不合适用到new了。

到底有没有一个“最合适”的做法呢?
我查了关于碎片的问题,一种说法是不用管它,这个似乎说不过去。另一个说法是使用内存池,不会为了这么简单的一个应用就去写一个复杂的池代码吧。

上面的4当然不是合适的了。那该怎么做?请高手们说一说自己的看法。
...全文
4319 200 打赏 收藏 转发到动态 举报
写回复
用AI写文章
200 条回复
切换为时间正序
请发表友善的回复…
发表回复
dvlinker 2010-02-06
  • 打赏
  • 举报
回复
学习了~
bilt719621 2010-01-08
  • 打赏
  • 举报
回复
怎么头越看越大...
ama1997 2009-11-28
  • 打赏
  • 举报
回复
如果不够了,再申请一块内存,将原先的数组的数据放进去,然后删除掉原来的数组……
zlalalal 2009-10-25
  • 打赏
  • 举报
回复
你写 小程序 觉得用池 有点过 但后来说到服务器 还有什么可迟疑的 那时当然要用内存池或其他机制来避免碎片化了
elite_lyh 2009-10-19
  • 打赏
  • 举报
回复
顶一下。太好了
thegodofwar 2009-10-19
  • 打赏
  • 举报
回复
很好,很强大
北京的雾霾天 2009-10-19
  • 打赏
  • 举报
回复
谢谢各位的回答。
xwsn007 2009-10-19
  • 打赏
  • 举报
回复
[Quote=引用 98 楼 qisamuelzhang 的回复:]
要不要考虑内存碎片关键看你的应用。如果是客户端程序,并无大碍;如果是服务器端的程序,即使有2G的用户空间,架不住长时间不启动,很快经年累月总有100%碎片的情况。

减少碎片采用memory pooling是很直观的方法,在Windows上面可以直接VirtualAlloc一大块内存,逐步commit,然后切割并通过比特位图来记录使用和释放,当然,为了效率的考量,最好使用free list等cache机制避免过多的commit/decommit甚至page fault。

更巧妙的方法是借助Windows中Low-fragmentation Heap,具体可以参考http://msdn.microsoft.com/en-us/library/aa366750(VS.85).aspx。简而言之,如果满足LFH的要求,Windows自带的Heap Manager会通过类似bag的算法即提高new的速度,又大大降低碎片。当然,在Vista/Win7中LFH会自动打开,不用程序员劳神。VC的CRT中的new是调用Heap Manager的,所以如果你用的是VC,只要满足LFH启动的要求,大可把增加白头发的事情交给微软那些程序员去!
[/Quote]

LFH 学习了!
gg606 2009-10-18
  • 打赏
  • 举报
回复
realloc 也不一定是“在原来内存的后面扩展空间”!
只有内存分配在CRT小块堆上时才有可能出现这种情况。

拙见:
如果内存大小变化的情况发生频繁,则采取第4种方案,否则第1种方案。
klkvc386 2009-10-18
  • 打赏
  • 举报
回复
Mark
这不是鸭头 2009-10-18
  • 打赏
  • 举报
回复
使用vector之类的C++内置数组类型。
vector比数组安全,效率还高
cllover 2009-10-18
  • 打赏
  • 举报
回复
学习中
cheng_fengming 2009-10-18
  • 打赏
  • 举报
回复
内存管理是C/C++中最值得关注的问题之一了。
abc_aaa_012 2009-10-18
  • 打赏
  • 举报
回复
阵容好强大,帮顶...
Email2k 2009-10-16
  • 打赏
  • 举报
回复
测试程序:
这个程序将进程内存分成2M的块进行分配,一直分配完。
然后隔一块释放一个。
这样内存变成了不连续的碎片。
这个时候按道理已经有几百M的空闲内存了,可是你分配10M内存也会失败。
这里用的是malloc,有兴趣的可以用new,HeapAlloc试试,结果应该是一样的。
由于占用大量内存,测试程序运行会很慢,整个机器也会很慢
#include <stdio.h>
#include <stdlib.h>

int main(int argc,char** argv)
{
int i,nMaxPointer;
int nPointerNumber=1024*1024;
char** pMemPoint=(char**)malloc(nPointerNumber*sizeof(char*));
for(i=0;i<nPointerNumber;i++)
{
pMemPoint[i]=(char*)malloc(2*1024*1024);
if (NULL==pMemPoint[i])
break;
}
nMaxPointer=i;
for(i=0;i<nMaxPointer;i=i+2)
{
delete pMemPoint[i];
}

printf("Max pointer=%d\n",nMaxPointer);
char* pNew=(char*)malloc(10*1024*1024);
if (pNew)
{
printf("Malloc successful\n");
}
else
{
printf("malloc failed\n");
}

return 0;
}
Email2k 2009-10-16
  • 打赏
  • 举报
回复
内存碎片问题的核心不在用什么管理内存,而在于C++的指针。
一旦使用指针,意味着这个内存的虚拟内存地址固定了,无法移动,那么任何内存管理方式都无法处理内存碎片了。
简单的举个例子,你如果将所有内存按照1024进行动态分配,然后每隔一个释放,之后你如果要分配2048字节就会失败,因为操作系统在进程地址空间中找不到一块2048的连续空闲内存,即使总的空闲内存远远大于2048。
这种情况下,除非系统对内存进行调整,否则它无法分配2048字节内存。比如将几个正在使用的1024内存块移动拼在一起,就可以空出2048字节来完成内存分配。
但是如果这些1024内存都是用指针访问的话,系统就无法进行这种移动,因为移动会导致指针失效,而使用指针系统是无法通知这个指针进行修改的(想象一下你的指针赋给一个指针变量了,然后系统的一次内存分配之后这个变量的值就变了!)。
和黑1 2009-10-16
  • 打赏
  • 举报
回复
Studying
panpengpeng 2009-10-16
  • 打赏
  • 举报
回复
好多牛人,学习
北京的雾霾天 2009-10-16
  • 打赏
  • 举报
回复
断续关注中。。。
平凡的思想者 2009-10-15
  • 打赏
  • 举报
回复
如果是小于512字节的内存,vc malloc会自己管理碎片,超过512字节的会交给系统的堆管理。
如果你担心内存碎片的问题,建议使用Loki来管理内存,方便而且高效。
加载更多回复(177)

16,472

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Web++
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧