Effective C++ 49. Understand the behavior of the new-handler

set_new_handler, a standaed library function declared in <new>

namespace std {
    typedef void (*new_handler)();
    new_handler set_new_handler(new_handler p) throw();
}

void outOfMem() {
    std::cerr << "Unable to satisfy request for memory\n";
    std::abort();
}
class Widget {
public:
    static std::new_handler set_new_handler(std::new_handler p) throw();
    sttic void * operator new(std::size_t size) throw(std::bad_alloc);
private:
    static std::new_handler currentHandler;
};

// static class members must be define outside the class 
// defination(unless they're const and integral)
std::new_handler Widget::currentHandler = 0;
// this is what the standard version of set_new_handler does
std::new_handler Widget::set_new_handler(std::new_handler p) throw() {
    std::new_handler oldHandler = currentHandler;
    currentHandler = p;
    return oldHandler;
}

// RAII(Resource Acquisition Is Initialization)
class NewHandlerHolder {
public:
    explicit NewHandlerHolder (std::new_handler nh): handler(nh) { }
    ~NewHandlerHolder() {
        std::set_new_handler(handler); 
    }
private:
    std::new_handler handler;
    NewHandlerHolder(const NewHandlerHolder&);
    NewHandlerHolder& 
        operator=(const NewHandlerHolder&);
}; 

void* Widget::operator new(std::size_t size) throw(std::bad_alloc) {
    NewHandlerHolder
        h(std::set_new_handler(currentHandler));
    return ::operator new(size);
}
// set outOfMem as Widget's new-handling funcion.
// if memory allocation fails, call outOfMem
void outOfMem();
Widget::set_new_handler(outOfMem); 
Widget *pwl = new Widget;

// if memory allocation fails, call the global new-handing 
// funcion
std::string *ps = new std::string;

// if mem.alloc fails, throw an exception immediately.
// (There is no new-handing function for class Widget.)
Widget::set_new_handler(0);
Widget *pw2 = new Widget;
template<typename T>
class NewHandlerSupport {
public:
    static std::new_handler set_new_handler(std::new_handler p) throw();
    static void* operator new(std::size_t size) throw(std::bad_alloc);
private:
    static std::new_handler currentHandler;
};

template<typename>
std::new_handler
NewHandlerSupport<T>::set_new_handler(std::new_handler p) throw() {
    std::new_handler olderHandler = currentHandler;
    currentHandler = p;
    return oldHandler;
}

template<typename T>
void* NewHandlerSuppor<T>::operator new(std::size_t size) throw(std::bad_alloc) {
    NewHandlerHolder h(std::set_new_handler(currentHandler));
    return ::operator new(size);
}

// this initializes each currentHandler to null
template<typename T>
std::new_handler NewHandlerSuppor<T>::currentHandler = 0;

class Widget: public NewHandlerSupport<Widget> {

    // as before, but without declarations for set_new_handler or operator new
    ...
}   
// throw bad_alloc if allocation fails
class Widget {... };
Widget *pw1 = new Widget;

// this test must fail
if (pw1 == 0) ...


// returns 0 if allocation for the Widget fails
Widget *pw2 = new(std::nothrow) Widget;

// this test must succeed
if (pw2 == 0) ...
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值