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

今天主要总结关于使用 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的扩展。

c++关于使用new的纠正的更多相关文章

  1. C#图片色彩的纠正-上

    WPF(C#)图片色彩的纠正-上 WPF(C#)图片色彩的纠正-下 前言 对图片进行色彩的纠正,其实与WPF是没有什么关系的,为什么标题又是“WPF(C#)图片色彩的纠正”呢,因为这些图片色彩的纠正功 ...

  2. 对属性NaN的理解纠正和对Number.isNaN() 、isNaN()方法的辨析

    1.属性NaN的误解纠正 NaN (Not a Number)在w3c 中定义的是非数字的特殊值 ,它的对象是Number ,所以并不是任何非数字类型的值都会等于NaN,只有在算术运算或数据类型转换出 ...

  3. CSS下拉列表错误纠正

    上一篇关于CSS制作下来列表的错误纠正. 在上一篇中,用CSS只做了下拉列表,但是鼠标不放在导航栏上的时候,下拉列表也是出来的.具体错误就是 div ul{ list-style:none; max- ...

  4. C# winform 若要在加载设计器前避免可能发生的数据丢失,必须纠正以下错误

    winform中有时添加了新控件之后编译会报错: 若要在加载设计器前避免可能发生的数据丢失,必须纠正以下错误,如图: 解决方案: 1.“解决方案”→“批生成”→“清理”→“确定”: 2.“解决方案”→ ...

  5. JAVA classpath, 纠正我一直以来错误的认知

    如何调在CLI中使用java tool(JDK中的java命令)调用一个打包在jar中的类,我想大多数人都能给出笼统的方案: java -classpath xxxxx com.test.classA ...

  6. VS2008 由于应用程序配置不正确,应用程序未能启动。重新安装应用程序可能会纠正这个问题。

    提示这个错误,自己的程序是在VS2008下编译的C/C++ win32程序,自己当时在win7上开发测试,都没有问题,正常使用,也在另一台xp系统上也试了,都没有问题.就发给客户了,没想到有些客户竟然 ...

  7. 关闭 Mac 拼写自动纠正与横线转换

    如果你是个程序员, 如果你恰好用 mac 自带的 notes 来做笔记, 很大可能性, 你会在里面贴代码, 但是, Mac 的拼写检查和自动纠正功能,会把代码变成你不想要的样子, 比如, 它会为你首字 ...

  8. 命令纠正工具 thefuck 的简单使用

    在unix系列的系统中,总会出现 命令拼写或者执行错误的情况, 比如 把 python 写成了pythou, cd 到一个不存在的目录,执行任务的权限 不够的问题, 这是心里 总是 在 fuck,但是 ...

  9. java 英文单词拼写纠正框架(Word Checker)

    Word Checker 本项目用于单词拼写检查. 项目简介 word checker 用于单词拼写检查. Github 地址 特性说明 支持 i18n 错误提示支持 i18N 支持英文的单词纠错 可 ...

  10. Noisy Channel模型纠正单词拼写错误

    本文介绍 Stanford<From Languages to Information>课程中讲到的 单词拼写错误 纠正.背后的数学原理主要是贝叶斯公式.单词拼写错误纠正主要涉及到两个模型 ...

随机推荐

  1. 洛谷 P4663 - [BalticOI 2008]魔法石(dp)

    题面传送门 A:我该是有多无聊来写这种题的题解啊 B:大概是因为这题题解区里没有题解所以我来写一篇了,说明我有高尚的济世情怀(大雾 跑题了跑题了 首先看到字典序第 \(i\) 小小可以自然地想到按位决 ...

  2. R语言与医学统计图形-【28】ggplot2扩展包ggrepel、ggsci、gganimate、ggpubr

    ggplot2绘图系统--扩展包ggrepel.ggsci.gganimate.ggpubr等 部分扩展包可在CRAN直接下载,有些需借助devtools包从Github下载. 1. ggrepel包 ...

  3. jmeter+ant输出测试报告

    jmeter自己本身可以输出html测试报告的,不过这种自带的测试报告特别简陋,如下图所示,一般我们是不看这种的. 我们可以使用ant来输出更高效.更直观的测试报告. 首先下载安装ant, 我用的是a ...

  4. java9 模块化 jigsaw

    java9并没有在语言层面做出很多改变,而是致力于一些新特性,如模块化,其核心就是解决历史遗留问题,为以后的jar包森林理清道路.模块化是一个很大的命题,就不讲那么细致了,关于java9的特性也有很多 ...

  5. Spark(十六)【SparkStreaming基本使用】

    目录 一. SparkStreaming简介 1. 相关术语 2. SparkStreaming概念 3. SparkStreaming架构 4. 背压机制 二. Dstream入门 1. WordC ...

  6. Attempt to invoke virtual method 'boolean java.lang.String.equals(java.lang.Object)' on a null objec

    遇到这个一场折腾了1个小时, 这是系统在解析XML的时候出错, 最后费了好大的劲才发现 XML文件中,<View>  写成小写的 <view> 了. 崩溃啊.......... ...

  7. 使用NSURLSessionDataTask实现大文件离线断点下载(完整)

    6.1 涉及知识点(1)关于NSOutputStream的使用 //1. 创建一个输入流,数据追加到文件的屁股上 //把数据写入到指定的文件地址,如果当前文件不存在,则会自动创建 NSOutputSt ...

  8. shell脚本采集系统cpu、内存、磁盘、网络信息

    有不少朋友不知道如何用shell脚本采集linux系统相关信息,包括cpu.内存.磁盘.网络等信息,这里脚本小编做下讲解,大家一起来看看吧. 一.cpu信息采集 1),采集cpu使用率采集算法:通过/ ...

  9. Kafaka相关命令

    开启zookeeper命令(备注:先进入zookeeper的bin目录) ./zkServer.sh start 关闭zookeeper命令(备注:先进入zookeeper的bin目录) ./zkSe ...

  10. springboot-devtools实现项目的自动重启

    热部署的引入依赖: <!-- 热部署 --> <dependency> <groupId>org.springframework.boot</groupId& ...