迈克老狼

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

1:C++标准说:An allocation function shall be a class member function or a global function; a program is ill-formed if an allocation function is declared in a namespace scope other than global scope or declared static in global scope.
必须是全局函数或类成员函数,而不能是全局之外的名字空间或static全局函数。

2:new operator的行为
对于如下代码:

1     foo* p = new(参数1,参数2,…… ) foo(……);
2     ……其他代码……
3     delete p;

编译器将生成如下代码:

 

 1     调用 p = operator new( size_t 需要的大小,参数1,参数2,…… ); // 这里有可能抛出std::bad_alloc,但无须在new operator中捕捉
 2     如果构造foo不会抛出异常 // 即foo的构造函数后面显式的声明了 throw()
 3         在p指向处构造foo(参数1,参数2,……);
 4         return p;
 5     否则
 6         try
 7         {
 8             在p指向处构造foo(参数1,参数2,……);
 9             return p;
10         }
11         catch()
12         {
13             调用 operator delete( void* p, 参数1,参数2,…… );
14             throw;
15         }
16     ……其他代码……
17     调用 operator delete( void* p );

从上面的描述可以看出两点:
    a. 除了第一个参数外,其它参数和 operator new 都相同的 operator delete 称为相匹配的 operator delete
    b. 相匹配的 operator delete 仅在 operator new 成功,对象构造失败时被调用。而其他地方则一直调用 operator delete( void* p )。
       (如果不这么设计的话,编译器得为每一个p绑定当初调用它的operator new相匹配的operator delete的地址,以及当初调用时的实参,汗!!! )

3:全局形式的operator new伪代码

 1 void* operator new( size_t size ) // 包括其他形式
 2 {
 3     if0 == size ) // 须要注意
 4         size = 1;
 5 
 6     while(1)
 7     {
 8         分配size字节内存;
 9         if(分配成功)
10             return 指向内存的指针;
11 
12         new_handler globalhandler = set_new_handler(0);
13         set_new_handler(globalhandler);
14 
15         if( globalhandler )
16             (*globalhandler)();
17         else
18             throw std::bad_alloc();
19     }
20 }
21 void operator delete( void* raw )
22 {
23     if0 == raw ) // 须要注意
24         return;
25     
26 }
27 

须要说明的是,编译器本身就隐含着一个 void* operator new( size_t ),所以重载全局operator new必须加其他参数以示区别。
一般重载分配函数时都会重载三个,分别是 void* operator new( size_t, …… ),void operator delete( void*, …… ),以及一般形式的 void operator delete( void* )。

4. set_new_handler的作用
    set_new_handler设置一个函数,此函数将在分配内存失败时被调用,见3中的代码。
    从3中的代码还能看得出,new_handler必须有主动退出的功能,否则就会导致operator new内部死循环。因此newhandler的一般形式是:

须要说明的是,没有类形式的set_new_handler,但这也无所谓,你可以自己写。(见《Effective C++ 2e》条款7)

 1     void mynewhandler()
 2     {
 3         if( 有可能使得operator new成功(比如释放部分内存) )
 4         {
 5             做有可能使得operator new成功的事
 6             return;
 7         }
 8         // 主动退出
 9         或 abort/exit 直接退出程序
10         或 set_new_handler(其他newhandler);
11         或 set_new_handler(0)
12         或 throw bad_alloc()或派生类 // 这一种比较好,不粗鲁的关闭程序,也不更改其他设置
13     }

5. 类形式的operator new伪代码:

在类中声明operator newoperator delete函数,则在调用newdelete分配类对象时,会自动调用类中的operator newoperator delete替换全局库中的
operator new operator delete版本。这些函数隐含式静态函数,也可以显示的指定为静态函数。当然如果想使用全局的new版本,则可以用::new的形式。

 

 1 struct base
 2 {
 3     
 4     static void* operator new( size_t size );
 5     static void operator delete( void* raw );
 6 };
 7 void* base::operator new( size_t size )
 8 {
 9     ifsizeof(base!= size ) // 须要注意
10         return ::operator new(size);
11 
12     类似于3 // 注意“没有类形式的set_new_handler”
13 }
14 void base::operator delete( void* raw )
15 {
16     ifsizeof(base!= size ) // 须要注意
17     {
18         ::operator delete(raw);
19         return;
20     }
21     同3
22 }
23 

原文地址:http://blog.vckbase.com/bruceteen/archive/2009/05/27/37427.html

posted on 2009-11-18 14:37  迈克老狼  阅读(474)  评论(0编辑  收藏  举报