std::nothrow
1、在内存不足时,new (std::nothrow)并不抛出异常,而是将指针置NULL。
若不使用std::nothrow,则分配失败时程序直接抛出异常。
2、使用方式:
1 #include <new> 2 #include <iostream> // for std::cerr 3 #include <cstdlib> // for std::exit() 4 Task * ptask = new (std::nothrow) Task; 5 if (!ptask) 6 { 7 std::cerr<<"allocation failure!"; 8 std::exit(1); 9 } 10 //... allocation succeeded; continue normally
1 #include <new> 2 std::nothrow_t nt; 3 Task * ptask = new (nt) Task; //user-defined argument 4 if (!ptask) 5 //...
3、分配失败是非常普通的,它们通常在植入性和不支持异常的可移动的器件中发生更频繁。因此,应用程序开发者在这个环境中使用nothrow new来替代普通的new是非常安全的。
4、一种宏实现的方式,取自ACE:
1 # define ACE_nothrow ::std::nothrow 2 # define ENOMEM 12 3 # define errno (* (ACE_CE_Errno::instance ())) 4 5 #if defined (ACE_NEW_THROWS_EXCEPTIONS) 6 # if defined (ACE_HAS_NEW_NOTHROW) 7 # define ACE_NEW_RETURN(POINTER,CONSTRUCTOR,RET_VAL) \ 8 do { POINTER = new (ACE_nothrow) CONSTRUCTOR; \ 9 if (POINTER == 0) { errno = ENOMEM; return RET_VAL; } \ 10 } while (0) 11 # define ACE_NEW(POINTER,CONSTRUCTOR) \ 12 do { POINTER = new(ACE_nothrow) CONSTRUCTOR; \ 13 if (POINTER == 0) { errno = ENOMEM; return; } \ 14 } while (0) 15 # define ACE_NEW_NORETURN(POINTER,CONSTRUCTOR) \ 16 do { POINTER = new(ACE_nothrow) CONSTRUCTOR; \ 17 if (POINTER == 0) { errno = ENOMEM; } \ 18 } while (0) 19 20 # else 21 22 # define ACE_NEW_RETURN(POINTER,CONSTRUCTOR,RET_VAL) \ 23 do { try { POINTER = new CONSTRUCTOR; } \ 24 catch (ACE_bad_alloc) { ACE_del_bad_alloc errno = ENOMEM; POINTER = 0; return RET_VAL; } \ 25 } while (0) 26 27 # define ACE_NEW(POINTER,CONSTRUCTOR) \ 28 do { try { POINTER = new CONSTRUCTOR; } \ 29 catch (ACE_bad_alloc) { ACE_del_bad_alloc errno = ENOMEM; POINTER = 0; return; } \ 30 } while (0) 31 32 # define ACE_NEW_NORETURN(POINTER,CONSTRUCTOR) \ 33 do { try { POINTER = new CONSTRUCTOR; } \ 34 catch (ACE_bad_alloc) { ACE_del_bad_alloc errno = ENOMEM; POINTER = 0; } \ 35 } while (0) 36 # endif /* ACE_HAS_NEW_NOTHROW */ 37 38 #else /* ACE_NEW_THROWS_EXCEPTIONS */ 39 40 # define ACE_NEW_RETURN(POINTER,CONSTRUCTOR,RET_VAL) \ 41 do { POINTER = new CONSTRUCTOR; \ 42 if (POINTER == 0) { errno = ENOMEM; return RET_VAL; } \ 43 } while (0) 44 # define ACE_NEW(POINTER,CONSTRUCTOR) \ 45 do { POINTER = new CONSTRUCTOR; \ 46 if (POINTER == 0) { errno = ENOMEM; return; } \ 47 } while (0) 48 # define ACE_NEW_NORETURN(POINTER,CONSTRUCTOR) \ 49 do { POINTER = new CONSTRUCTOR; \ 50 if (POINTER == 0) { errno = ENOMEM; } \ 51 } while (0) 52 #endif
使用时:
1 ACE_Thread_Descriptor *thr_desc = 0; 2 ACE_NEW_RETURN (thr_desc, 3 ACE_Thread_Descriptor, 4 -1);