有一个著名的原则,叫做KISS -- keep it simple and stupid。大概就是说,能简单就简单,简单的实现方式更可靠,过犹不及。
以处理new中的exception为例。为了编写完美的异常安全的代码,有必要保持对任何已分配资源的跟踪并且时刻准备着当异常发生时释放他们。我们既可以将代码组织为无需回收资源的方式(参考http://blog.csdn.net/fishhg/article/details/6647822(编写异常安全的代码)),也可以使用资源句柄来自动回收资源(参考http://blog.csdn.net/fishhg/article/details/6413605(RAII))。在极端情况下,还可以使用肮脏的try语句块甚至嵌套的try语句块;但这应该视为一个例外,而不应作为应该奉行的准则。
new实际上执行两个不同的操作:首先,它调用一个operater new来分配一些memor,然后调用某一个构造函数将这片memory初始为一个对象。其中的问题是,如果发生一个异常,我们说不清到底这两者哪一个抛出来的。区分这一点很重要,涉及到释放需要归还memory的问题。
一种恐怖的方式是手工编写具有正确行为的代码,这是通过将分配和初始化行为分离并借助一个try语句块完成的:
string * title = static_cast<string*> (::operator new (sizeof(string));
try{
new(title) string("kicks");
}
catch( ...){
::opertor delete(title);
}
这段代码有很多错误。举一个反例,如果string一个成员operator new和一个成员operator delete的话,这段代码将无法正确工作。看到没有,聪明反被聪明误!过于聪明的代码,一开始或许可以工作,但在将来可能会因一些细微的改变而失败。
幸运的是,编译器可以帮我们处理这种情形,并且自动生成与上述手工编码方式相同的代码。只不过,它会调用合适的new。
string * title = new string("kicks");//使用成员operator new -- 如果提供了的话
string * title = ::new string("kicks");//使用全局new/delete