new (nothrow) T() 的原理

查看<new>中对new的声明.

void* operator new(std::size_t) throw (std::bad_alloc);

void* operator new(std::size_t, const std::nothrow_t&) throw();

void* operator new[](std::size_t) throw (std::bad_alloc);

void* operator new[](std::size_t, const std::nothrow_t&) throw();

 

如果使用,new T () 程序,调用 void* operator new(std::size_t) throw (std::bad_alloc); 在内存不足的情况下,将抛出bad_alloc异常.

如果使用,new (nothrow) T () 程序,调用 void* operator new(std::size_t, const std::nothrow_t&) throw(); 拥有空异常修饰符,不允许抛出任何异常,其定义中,如果内存不足返回值为0.

 

 C++11标准中:

throw() 已经被弃用,而使用noexcept “异常声明” 替代。

void f() noexcept {...} // 函数不抛出任何异常,如果函数体出现异常,程序直接中断

void f() noexcept(true){...} // 同上

void f() noexcept(false) {...} // 函数允许抛出异常,如果函数提出现异常,将向上抛出异常


C++11中取消了:void f() throw (int ,double) {...}  这种指定函数抛出异常类型的方式,以void f() noexcept(false) {...}  取代。


但,目前看来,支持C++11标准的编译器实际上也没有准训以上标准,任然使用以前的格式。更多可以参见gnu 4.8.2源码



/* 
 * File:   Player.h
 * Author: Vicky.H
 * Email:  eclipser@163.com
 *
 * Created on 2014年1月21日, 下午7:17
 */

#ifndef PLAYER_H
#define	PLAYER_H

#define NDEBUG

#if defined(__cplusplus) && (__cplusplus >= 201103) // C++11
    #ifndef NDEBUG
        #define VNOECEPT noexcept(true)  // debug版本,不允许析构函数等抛出异常
    #else
        #define VNOECEPT noexcept(false) // release版本,允许析构函数等抛出异常
    #endif
#else
    #ifndef NDEBUG
        #define VNOECEPT throw()  // debug版本,不允许析构函数等抛出异常
    #else
        #define VNOECEPT          // release版本,允许析构函数等抛出异常
    #endif
#endif

class Player {
public:
    Player();
    Player(const Player& orig);
    virtual ~Player() VNOECEPT /**一般析构函数都不允许抛出异常,*/;
private:

};

#endif	/* PLAYER_H */

/* 
 * File:   Player.cpp
 * Author: Vicky.H
 * Email:  eclipser@163.com
 * 
 * Created on 2014年1月21日, 下午7:17
 */

#include "Player.h"

Player::Player() {
}

Player::Player(const Player& orig) {
}

Player::~Player() VNOECEPT {
    throw "~Player() not allow throw exception, but throwed";
}

/* 
 * File:   main7.cpp
 * Author: Vicky.H
 * Email:  eclipser@163.com
 */
#include <iostream>
#include <new>
#include "Player.h"

void f1() throw () {
    std::cout << "f1()" << std::endl;
}

// C++11标准

void f2() noexcept { // 不抛出异常 noexcept = noexcept(true)
    std::cout << "f2()" << std::endl;
}

template <typename T>
const T& max(const T& o1, const T& o2) noexcept(false) { // 要抛出异常
    return o1 > o2 ? o1 : o2;
}

template<>
const int& max(const int& o1, const int& o2) noexcept(false){ // noexcept(true) ERROR 当模版设置为要抛出异常,儿模版的范例却不抛出异常将导致错误
    return o1 < o2 ? o1 : o2;
}

/*
 * 
 */
int main(void) {
    f1();
    f2();
    std::cout << "\n---------------------------" << std::endl;
    std::cout << max(1.0, 2.0) << std::endl;
    std::cout << max(1, 2) << std::endl;
    std::cout << "\n---------------------------" << std::endl;
    
    try {
        Player* p = new Player();
        delete p;
    } catch (...) {
        std::cout << "except happen" << std::endl;
    }
    return 0;
}



  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C++内存泄漏检测原理+实例源码下载,是一个跨平台的C++ 内存泄漏检测器的源程序,一个主要缺陷是不支持多线程。分配内存时不进行文件名复制,而只是保存其指针;效率较高(编译debug_new.cpp  时有效;参见文件中的注释)   我本人认为,debug_new目前的一个主要缺陷是不支持多线程。对于某一特定平台,要加入多线程支持并不困难,难就难在通用上(当然,条件编译是一个办法,虽然不够优雅)。   等到C++标准中包含线程模型时,这个问题也许能比较完美地解决吧。另一个办法是使用像boost这样的程序库中的线程封装类,不过,这又会增加对其它库的依赖性--毕竟boost并不是C++标准的一部分。如果项目本身并不用boost,单为了这一个目的使用另外一个程序库似乎并不值得。因此,我自己暂时就不做这进一步的改进了。   另外一个可能的修改是保留标准operator new的异常行为,使其在内存不足的情况下抛出异常(普通情况)或是返回NULL(nothrow情况),而不是像现在一样终止程序运行(参见debug_new.cpp 的源代码)。这一做法的难度主要在于后者:我没想出什么方法,可以保留 new(nothrow) 的语法,同时能够报告文件名和行号,并且还能够使用普通的new。不过,如果不使用标准语法,一律使用debug_new和debug_new_nothrow的话,那还是非常容易实现的。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值