返回   cpper编程论坛 > 技术杂烩
注册账号 论坛帮助 会员列表 日历事件 搜索 今日新帖 标记版面已读

技术杂烩 找不到地方的技术问题?这里!

关闭主题
 
LinkBack 主题工具 显示模式
  #1 (permalink)  
旧 2003-11-19
polyrandom 的头像
超级版主
 
注册日期: 2002-09-03
帖子: 3,138
文章: 20
polyrandom 正向着好的方向发展
默认 new/delete不完全手册

new/delete不完全手册
--------------------------------------------------------
这是一份未完成的文档,本来想等完全完成后再贴出,可是我发现如果我不是写一点就贴一点的话,那么永远都没有完成的时候了。

我争取让一个人看了这个帖子可以学会所有和new/delete有关的知识。
我会不断补充的,需要知道什么,有什么问题,也请告诉我。(论坛消息)

0
我们在C++里面在堆上创建一个对象的时候,通常使用的方法就是new。譬如说,下面这段代码创建了一个具有两个元素的T的数组。
代码:
T* p=new T[2];
我们平时说的new,从概念上说,可分为new operator和operator new。上述程序里面的这个new就是new operator,new operator调用operator new分配内存,然后再调用对象的构造函数。你是不能去重载new operator的,你只能重载operator new。也就是说,你只能干预对象的内存是怎么分配的,但是你不能干预对象创建的过程。标准文献上从未有类似于delete operator的记载,但是我们可以认为delete也分为delete operator和operator delete;前者先调用析构函数,再调用后者释放内存。下面我们说起new/delete的时候,应该可以根据上下文判断所说的是什么。
所有的operator new/operator delete成员函数,都是static的,即使你没有写static。operator new/operator delete和普通成员函数一样,可以被继承,可以被显式调用,会被掩盖。

1
new T;
其过程是:首先,调用T:perator new(如果没有定义的话,可以认为编译器会给出一个缺省定义。)分配内存,然后再对这个新分配的内存调用T的ctor。
如果调用T:perator new的时候,有异常抛出,则ctor不会被调用,而且该异常会继续向上抛出。如果调用ctor的时候抛出异常,那么会调用T:perator delete来释放这段内存,并且异常会被向上抛出。(T::dtor不会被调用
如果调用T:perator new的时候,返回NULL,则ctor不会被调用,返回NULL。但是,如果你要让你的T:perator new返回NULL,你应该把它的exception specification写成throw();否则就应该在错误的情况下抛出std::bad_alloc。
返回NULL的情况写成代码如下:
代码:
T* p=(T*)T::operator new(sizeof(T)); if(!p) { try { p->T::T(); } catch(...) { T::operator delete(sizeof(T)); throw; } } return p;
2
new T[x];
其过程是:首先,调用T:perator new[](如果没有定义的话,可以认为编译器会给出一个缺省定义。注意,不是调用多次T:perator new或者以size*x来调用一次T:perator new)分配内存,然后再对这个新分配的内存中的每个T调用T的ctor。(从第一个起,到最后一个。)
如果在调用T:perator new[]的时候,有异常抛出,那么后面的ctor将不会被调用到。异常会被向上抛出。
如果调用某个ctor的时候,有异常抛出,那么这个对象的dtor将不会被调用,而会对前面已经调用过ctor的对象调用dtor,其方向是从最后一个被初始化的起到第一个。然后调用T:perator delete[]释放内存并将异常向上抛出。
注意,operator new[]的size参数会>=所要分配的对象的size*个数。
譬如说:
T* t=new T[3];在调用t[2]的ctor的时候抛出异常,那么会先调用t[1]的dtor,再调用t[0]的dtor,再调用T:perator delete[],然后再把这个异常向上抛出。
写成代码如下:
代码:
char* pc=T::operator new[](sizeof(T)*x+MARK_SIZE); T* p=(T*)(pc+MARK_SIZE); int i; try { for(i=0;i<x;++i) p[i].T::T(); } catch(...) { --i; while(i>=0) p[i].T::~T(); T::operator delete[](pc); throw; } return p;
3
delete T;
很简单,先调用dtor,再释放内存。如果调用dtor的时候有异常抛出,那么继续向上抛,不释放内存。
4
delete[] T;
先反向调用dtor,再释放内存。如果调用dtor的时候有一个异常抛出,那么继续调用下面的dtor,然后再向上抛,内存不会被释放。如果在继续调用下面的dtor的时候,又有异常产生,bad_exception。
写成代码如下:
代码待补充
5
为什么delete/new和delete[]/new[]要配对使用。
解释待补充
class SomeClass
{
public:
void* operator new[](size_t size)
{
cout<<size<<endl;
return NULL;
}
};
int main()
{
SomeClass objects[2];
cout<<sizeof(SomeClass)<<endl;
cout<<sizeof(objects)<<endl;
new SomeClass[2];
return 0;
}
6
new(nothrow) T;
7
new T;
8
operator new and new operator
9
一些有趣的应用:
a.让一个类ctor发生异常,new返回NULL。
b.让一个类只能用new创建。
......

Reference:
The C++ PL, by Bjarne Stroustrup
ISO 14882
ECPP/MECPP CD, by Scott Meyer
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
关闭主题

书签

主题工具
显示模式

发帖规则
不可以发表新主题
不可以发表回复
不可以上传附件
不可以编辑自己的帖子

启用 BB 代码
论坛启用 表情符号
论坛启用 [IMG] 代码
论坛禁用 HTML 代码
Trackbacks are 启用
Pingbacks are 启用
Refbacks are 启用



所有时间均为格林尼治时间 +9。现在的时间是 10:46 PM


Powered by vBulletin® 版本 3.7.0
版权所有 ©2000 - 2009,Jelsoft Enterprises Ltd.
(C) Copy Right All Right Reserved 2001 - 2007

Search Engine Friendly URLs by vBSEO 3.1.0