c++关于使用new的纠正
2021-06-12 04:02
标签:就会 为什么 lease void std 编译器 修改 struct 代码 自己之前纠正过这个问题,但还是忘了。今天再拿出来。 今天主要总结关于使用 c++ 标准中的 new 关键字。 【结论】 A、处理new可能抛出的异常 B、针对new使用std::nothrow不抛出异常 1、错误示范 下面一段代码,使用new向堆申请空间,再释放的过程 A、代码中 第 3 行 有错误, 准确的说是 这样写不够规范。为什么? B、因为: 第3行代码 结果有两种: 1)、申请空间成功,并且返回申请成功的地址 2)、 申请失败,则抛出异常: std::bad_alloc (重点),而不是返回 NULL 或者 nullptr. 当然, 上面第4行代码也不会执行。 C、那,怎么改? 2、正确做法 上面分析到了,是因为使用不规范引起的。下面就是规范的写法。修改方法有 2 种。 A、使用 std::nothrow 对比上面错误的做法, 变化就在 第3行。 这样就可以了: 申请空间失败, 就会返回 NULL, 当前也会继续执行 第3行以后的代码。 B 、既然 new 可能会抛出异常std::badalloc,那么,我们就需要处理异常。 对比上面的错误示范,变化: 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 这个是? 别急, 定义如下: 其实也是继承的 std::exception 。 这里出现了友元类: bad_array_new_length, 我们再看看他的定义 原来是这样。 5、new/delete 定义 下面是来自VS2015 up3中的new和delete的源码 vcruntime_new.h: 下面的代码 已经掐头去尾 可以看到 , 上面的代码中 可以看到 声明中存在不会抛出异常的定义,大胆推测,可能是为了延续C的判断指针是否为NULL的扩展。 c++关于使用new的纠正 标签:就会 为什么 lease void std 编译器 修改 struct 代码 原文地址:https://www.cnblogs.com/pandamohist/p/13519719.html 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;
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;
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: " endl;
10 return;
11 }
12
13 // 2、doing sth
14
15 // 3、release
16 delete pbuf;
17 pbuf = NULL;
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 };
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 };
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