关于 Effective C++ 的 Item 7 中重载 new 运算符的问题
在这篇文章中,作者提供了一个模板类 NewHandlerSupport 的实现,其中定义并实现了成员函数 set_new_handler(),但是似乎并没有用到,只用到了 std::set_new_handler()。
我在我的测试程序中注释掉这个成员函数的定义和实现,程序照样可以编译并运行。
我在程序中 set_new_handler() 的实现的最前面加入一条输出语句。然后让程序在无限循环中不断调用重载的 new 运算符,但是直到抛出异常,也没有执行到我的那条输出语句。
既然没有用到,那么在模板类中实现 set_new_handler() 有什么用呢?
希望看过这篇文章的高手能解答我的疑问。
问题点数:60、回复次数:8Top
1 楼fatalerror99(iTePub's Nirvana)回复于 2005-04-07 17:33:26 得分 0
还有,如果我把重载的 new 中的 std::set_new_handler() 都换成 NewHandlerSupport::set_new_handler() 是不是可以呢?我试了一下,没发现有什么问题,作者为什么定义了 NewHandlerSupport::set_new_handler(),而在可以用的时候却又去用 std::set_new_handler() 呢?Top
2 楼thomasnew(重新得到)回复于 2005-04-07 18:25:04 得分 60
文章说的很清楚啊,对照下面几句话:(全是原话,我看的是lostmouse翻译的)
“这个方法基于一个常规,即当operator new不能满足请求时,会在抛出异常之前调用客户指定的一个出错处理函数——一般称为new-handler函数。(operator new实际工作起来要复杂一些,详见条款8)
”
---
::就是说,new不成功时,你安装的new hander是自动被调用的。
“set_new_handler的输入参数是operator new分配内存失败时要调用的出错处理函数的指针,返回值是set_new_handler没调用之前就已经在起作用的旧的出错处理函数的指针。”
---
::这个就记住吧
下面这些说明,很明白啊,说明加代码,代码中还有注释,模板只是把不相干的类型换成了T,看x类的实现就好理解了
---------------------
最后看看x的operator new所做的:
1. 调用标准set_new_handler函数,输入参数为x的出错处理函数。这使得x的new-handler函数成为全局new-handler函数。注意下面的代码中,用了"::"符号显式地引用std空间(标准set_new_handler函数就存在于std空间)。
2. 调用全局operator new分配内存。如果第一次分配失败,全局operator new会调用x的new-handler,因为它刚刚(见1.)被安装成为全局new-handler。如果全局operator new最终未能分配到内存,它抛出std::bad_alloc异常,x的operator new会捕捉到它。x的operator new然后恢复最初被取代的全局new-handler函数,最后以抛出异常返回。
3. 假设全局operator new为类型x的对象分配内存成功,, x的operator new会再次调用标准set_new_handler来恢复最初的全局出错处理函数。最后返回分配成功的内存的指针。
c++是这么做的:
void * x::operator new(size_t size)
{
new_handler globalhandler = // 安装x的new_handler
std::set_new_handler(currenthandler);
void *memory;
try { // 尝试分配内存
memory = ::operator new(size);
}
catch (std::bad_alloc&) { // 恢复旧的new_handler
std::set_new_handler(globalhandler);
throw; // 抛出异常
}
std::set_new_handler(globalhandler); // 恢复旧的new_handler
return memory;
}
---------------------Top
3 楼fatalerror99(iTePub's Nirvana)回复于 2005-04-07 18:40:22 得分 0
就是说,new不成功时,你安装的new hander是自动被调用的。
这个恐怕不对吧,所谓的“即当operator new不能满足请求时,会在抛出异常之前调用客户指定的一个出错处理函数——一般称为new-handler函数”,是因为在 std::new 的实现中调用了这个函数,如果你重载 new 的话,必须在重载的实现中显式调用。
你引用的这段我只仔细看过的,但我的疑问也正是来自于这一段,他定义了自己的 set_new_handler 函数,为什么不去使用,却使用标准的 std::set_new_handler() 。Top
4 楼fatalerror99(iTePub's Nirvana)回复于 2005-04-07 18:47:10 得分 0
还有,我说过我在 NewHandlerSupport::set_new_handler() 中加了一条输出语句,却直到抛出异常也没有执行到,说明根本就没有调用到 NewHandlerSupport::set_new_handler()。因为重载的 new 中调用的都是 std::set_new_handler() 。Top
5 楼thomasnew(重新得到)回复于 2005-04-07 18:48:01 得分 0
new 中做的是设置好那个要被自动调用的函数,但并不是在new中调用的,
你要安装自己的new hander,就要重载new,用来安装自己的new handerTop
6 楼thomasnew(重新得到)回复于 2005-04-07 19:01:02 得分 0
我说过我在 NewHandlerSupport::set_new_handler() 中加了一条输出语句,却直到抛出异常也没有执行到.说明根本就没有调用到 NewHandlerSupport::set_new_handler()。因为重载的 new 中调用的都是 std::set_new_handler() 。
----------------------------
只是说明,没有用你的set_new_hander()来安装new hander,原因你自己说出来了,“因为重载的 new 中调用的都是 std::set_new_handler() ”
再看看这段话:
"类x中的set_new_handler函数会保存传给它的任何指针,并返回在调用它之前所保存的任何指针。这正是标准版本的set_new_handler所做的:
new_handler x::set_new_handler(new_handler p)
{
new_handler oldhandler = currenthandler;
currenthandler = p;
return oldhandler;
}
Top
7 楼thomasnew(重新得到)回复于 2005-04-07 19:05:37 得分 0
你要安装自己的new hander,就要重载new,用来安装自己的new hander
------
这句有问题,呵呵,sorry。
x的set_new_hander 和标准的set_new_hander(我们看到的)功能一样,所以用哪个都可以Top
8 楼fatalerror99(iTePub's Nirvana)回复于 2005-04-07 22:15:50 得分 0
既然X的set_new_hander 和标准的set_new_hander(我们看到的)功能一样,那为什么还要自己写一个set_new_hander 呢?一直用标准的不也可以嘛。Top




