c++关于使用new的纠正

365bet开户网站 ⌛ 2025-09-07 06:07:45 ✍️ admin 👁️ 2203 ❤️ 878
c++关于使用new的纠正

自己之前纠正过这个问题,但还是忘了。今天再拿出来。

今天主要总结关于使用 c++ 标准中的 new 关键字。

【结论】

A、处理new可能抛出的异常

B、针对new使用std::nothrow不抛出异常

1、错误示范

下面一段代码,使用new向堆申请空间,再释放的过程

1 char *pbuf = NULL;

2 // 这里有bug, 后面讲

3 pbuf = new char[128];

4

5 if ( NULL == pbuf)

6 {

7 std::cout << "\n error, pbuf created failure\n";

8 }

9

10 // 2、doing sth

11

12 // 3、release

13 delete pbuf;

14 pbuf = NULL;

A、代码中 第 3 行 有错误, 准确的说是 这样写不够规范。为什么?

B、因为: 第3行代码 结果有两种:

1)、申请空间成功,并且返回申请成功的地址

2)、 申请失败,则抛出异常: std::bad_alloc (重点),而不是返回 NULL 或者 nullptr. 当然, 上面第4行代码也不会执行。

C、那,怎么改?

2、正确做法

上面分析到了,是因为使用不规范引起的。下面就是规范的写法。修改方法有 2 种。

A、使用 std::nothrow

1 char *pbuf = NULL;

2 // 这里有bug, 后面讲

3 pbuf = new(std::nothrow) char[128];

4

5 if ( NULL == pbuf)

6 {

7 std::cout << "\n error, pbuf created failure\n";

8 }

9

10 // 2、doing sth

11

12 // 3、release

13 delete pbuf;

14 pbuf = NULL;

对比上面错误的做法, 变化就在 第3行。 这样就可以了: 申请空间失败, 就会返回 NULL, 当前也会继续执行 第3行以后的代码。

B 、既然 new 可能会抛出异常std::badalloc,那么,我们就需要处理异常。

1 char *pbuf = NULL;

2 try

3 {

4 // 1、需要处理可能抛出的异常

5 pbuf = new char[128];

6 }

7 catch (const std::bad_alloc& error)

8 {

9 std::cout << "\nerror: " << error.what() << endl;

10 return;

11 }

12

13 // 2、doing sth

14

15 // 3、release

16 delete pbuf;

17 pbuf = NULL;

对比上面的错误示范,变化:

1)、增加了对 new 发出异常的捕获。

2)、去掉了对指针为NULL的判断。

这里的代码, new 失败后, 将不会返回NULL, 而是抛出异常。 需要对异常处理。显然: 判断 if (NULL == pbuf) 就完全失去意义了。

所以,判断new是否返回成功,则需要添加对异常的处理。

3、为什么?

(以下均为个人观点)市面上的编译器 可谓雨后春笋。 new 和 delete 族当然不一样。 但总体原则:

A、 new(std::nothrow) 的方式是沿袭了C的习惯。

B、new 抛出异常的形式 则是 标准呢c++的形式。

C、为什么有这样两种的形式? 直接使用 c++标准的的形式不好吗? 但是需要考虑兼容,C语言中, 判断指针为NULl习惯是个好习惯,可以继续沿袭。而new抛出异常的c++标准方式是对 C的扩展。

D、这样做,既是对C的编程习惯的延续,又扩展了c++关于new定义,满足c++的标准形式。双赢。

4、std::badalloc

这个是? 别急, 定义如下:

1 class bad_alloc

2 : public exception

3 {

4 public:

5

6 bad_alloc() throw()

7 : exception("bad allocation", 1)

8 {

9 }

10

11 private:

12

13 friend class bad_array_new_length;

14

15 bad_alloc(char const* const _Message) throw()

16 : exception(_Message, 1)

17 {

18 }

19 };

其实也是继承的 std::exception 。 这里出现了友元类: bad_array_new_length, 我们再看看他的定义

1 class bad_array_new_length

2 : public bad_alloc

3 {

4 public:

5

6 bad_array_new_length() throw()

7 : bad_alloc("bad array new length")

8 {

9 }

10 };

原来是这样。

5、new/delete 定义

下面是来自VS2015 up3中的new和delete的源码 vcruntime_new.h: 下面的代码 已经掐头去尾

1 namespace std

2 {

3 struct nothrow_t { };

4

5 extern nothrow_t const nothrow;

6 }

7 #endif

8

9 _Ret_notnull_ _Post_writable_byte_size_(_Size)

10 _VCRT_ALLOCATOR void* __CRTDECL operator new(

11 size_t _Size

12 );

13

14 _Ret_maybenull_ _Success_(return != NULL) _Post_writable_byte_size_(_Size)

15 _VCRT_ALLOCATOR void* __CRTDECL operator new(

16 size_t _Size,

17 std::nothrow_t const&

18 ) throw();

19

20 _Ret_notnull_ _Post_writable_byte_size_(_Size)

21 _VCRT_ALLOCATOR void* __CRTDECL operator new[](

22 size_t _Size

23 );

24

25 _Ret_maybenull_ _Success_(return != NULL) _Post_writable_byte_size_(_Size)

26 _VCRT_ALLOCATOR void* __CRTDECL operator new[](

27 size_t _Size,

28 std::nothrow_t const&

29 ) throw();

30

31 void __CRTDECL operator delete(

32 void* _Block

33 ) throw();

34

35 void __CRTDECL operator delete(

36 void* _Block,

37 std::nothrow_t const&

38 ) throw();

39

40 void __CRTDECL operator delete[](

41 void* _Block

42 ) throw();

43

44 void __CRTDECL operator delete[](

45 void* _Block,

46 std::nothrow_t const&

47 ) throw();

48

49 void __CRTDECL operator delete(

50 void* _Block,

51 size_t _Size

52 ) throw();

53

54 void __CRTDECL operator delete[](

55 void* _Block,

56 size_t _Size

57 ) throw();

58

59 #ifndef __PLACEMENT_NEW_INLINE

60 #define __PLACEMENT_NEW_INLINE

61 _Ret_notnull_ _Post_writable_byte_size_(_Size)

62 inline void* __CRTDECL operator new(size_t _Size, _Writable_bytes_(_Size) void* _Where) throw()

63 {

64 (void)_Size;

65 return _Where;

66 }

67

68 inline void __CRTDECL operator delete(void*, void*) throw()

69 {

70 return;

71 }

72 #endif

73

74 #ifndef __PLACEMENT_VEC_NEW_INLINE

75 #define __PLACEMENT_VEC_NEW_INLINE

76 _Ret_notnull_ _Post_writable_byte_size_(_Size)

77 inline void* __CRTDECL operator new[](size_t _Size, _Writable_bytes_(_Size) void* _Where) throw()

78 {

79 (void)_Size;

80 return _Where;

81 }

82

83 inline void __CRTDECL operator delete[](void*, void*) throw()

84 {

85 }

86 #endif

可以看到 , 上面的代码中 可以看到 声明中存在不会抛出异常的定义,大胆推测,可能是为了延续C的判断指针是否为NULL的扩展。

相关推荐

APPBET365 林行止专栏:点球博弈论

林行止专栏:点球博弈论

⌛ 08-27 👁️ 4643
新日博365 苹果手机下载两个微信的方法
新日博365 目前主流的CPU有哪些?选择依据有哪些?
新日博365 为了患者

为了患者

⌛ 07-07 👁️ 381