一、 关于new的故事
首先,看看为什么说在C++中尽量用new/delete而不是malloc/free?
因为new/delete会隐式的调用对象的构造函数和析构函数,
stringstringarray1=
static_cast<string>(malloc(10sizeof(string)));
stringstringarray2=newstring[10];
其结果是,stringarray1确实指向的是可以容纳10个string对象的足够空间,但内存里并没有创建这些对象,而且,没有办法来初始化数组里的对象。换句话说,stringarray1其实一点用也没有。相反,stringarray2指向的是一个包含10个完全构造好的string对象的数组,每个对象可以在任何读取string的操作里安全使用。
假设你想了个怪招对stringarray1数组里的对象进行了初始化,那么在你后面的程序里你一定会这么做:
free(stringarray1);
delete [] stringarray2;
调用free将会释放stringarray1指向的内存,但内存里的string对象不会调用析构函数,如果string对象象一般情况那样,自己已经分配了内存,那这些内存将会全部丢失。相反,当对stringarray2调用delete时,数组里的每个对象都会在内存释放前调用析构函数。做如下测试
classTest
{
public:
Test(intsize=100)
{
_str=newchar[size];
cout<<"hold memory in constructor"<<endl;
}
~Test(void)
{
delete[] _str;
cout<<"release memory in destructor"<<endl;
}
private:
char_str;
};
intmain(void)
{
TestpTest=newTest[3];
delete[] pTest;
cout<<"------------------------------------"<<endl;
TestpTest2=static_cast<Test>(malloc(3*sizeof(Test)));
free(pTest2);
return0;
}
上面的测试显示了new/delete和malloc/free的区别,如果用new分配了对象然后用free释放有什么后果不难想象。
内存终究是有限的,那么分配内存就可能会失败,在通常自己写的一些小程序里鲜有分配内存失败的情况,但是在分配大块内存、尤其是内存容量较小比如嵌入式系统的时候还是很有可能发生,C语言里分配内存失败的时候就返回一个空值0,所以经常看到有这样的代码:
typep=(type)malloc(size);
if(p==0)...
C语言中这种处理方式是可行的,但是C++中则未必,早期C++一直要求在内存分配失败时operator new要返回0,现在则是要求operator new抛出std::bad_alloc异常。很多C++程序是在编译器开始支持新规范前写的。c++标准委员会不想放弃那些已有的遵循返回0规范的代码,所以他们提供了另外形式的operator new以及operator new[]以继续提供返回0功能。这些形式被称为“无抛出”,他们在使用new的入口点采用了nothrow对象,但是在new内存的时候如果不声明nothrow则内存分配失败时会抛出bad_alloc的异常,这时用如上C语言的方式检测成功与否就未必可行,下面的例子在VS2005下进行测试
voidtest(void)
{
unsignedlongsize=150010241024;
charmem1=new(nothrow)char[10size];//若分配失败返回0
if(!mem1)//这个检查可能会成功
{
cout<<"allocate 1 failed"<<endl;
}
charmem2=newchar[10size];//分配失败抛出std::bad_alloc
if(!mem2)//这个检查一定失败
{
cout<<"allocate 2 failed"<<endl;
}
}
测试结果是"allocate 1 failed",由于没有处理程序在分配mem2失败时的异常,因此执行到分配mem2的时候崩溃,解决方法是用try{}catch(std::bad_alloc&)捕获内存分配失败的异常。
另外,C++里用set_new_handler来设置失败的处理函数,比如在处理函数里先释放空闲内存然后再次请求内存分配,其形式为
typdefvoid(*new_handler)();
new_handler set_new_handler(new_handler p)throw();
set_new_handler的形式大致如下, 具体见
new_handler set_new_handler(new_handler p)
{
new_handler old_handler=current_handler;
current_handler=p;
returnold_handler;
}
二、placement new
标准C++支持在一分配的内存上构造对象,这一点在构建内存池时很有效
Operator new allocates memory from the heap, on which an object is constructed. Standard C++ also supports placement new operator, which constructs an object on a pre-allocated buffer. This is useful when building a memory pool, a garbage collector or simply when performance and exception safety are paramount (there's no danger of allocation failure since the memory has already been allocated, and constructing an object on a pre-allocated buffer takes less time):
void placement() {
char *buf = new char[1000]; //pre-allocated buffer
string *p = new (buf) string("hi"); //placement new
string *q = new string("hi"); //ordinary heap allocation
cout<c_str()<c_str();<
可参考的博文:
参加内存池管理
http://www.ecjtu.org/forum/read.php?tid-25583.html
代码实现??
placement new
http://www.cppblog.com/jacky2019/archive/2007/04/06/21375.html
http://www.ecjtu.org/forum/read.php?tid-25583.html
静态快上内存分配(除了不在堆区实际相当于内存池)
http://www.cppblog.com/expter/archive/2009/08/16/93511.aspx
原文链接: https://www.cnblogs.com/cnspace/archive/2010/05/25/AllocMemory.html
欢迎关注
微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍
原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/11162
非原创文章文中已经注明原地址,如有侵权,联系删除
关注公众号【高性能架构探索】,第一时间获取最新文章
转载文章受原作者版权保护。转载请注明原作者出处!