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的扩展。
c++关于使用new的纠正的更多相关文章
- C#图片色彩的纠正-上
WPF(C#)图片色彩的纠正-上 WPF(C#)图片色彩的纠正-下 前言 对图片进行色彩的纠正,其实与WPF是没有什么关系的,为什么标题又是“WPF(C#)图片色彩的纠正”呢,因为这些图片色彩的纠正功 ...
- 对属性NaN的理解纠正和对Number.isNaN() 、isNaN()方法的辨析
1.属性NaN的误解纠正 NaN (Not a Number)在w3c 中定义的是非数字的特殊值 ,它的对象是Number ,所以并不是任何非数字类型的值都会等于NaN,只有在算术运算或数据类型转换出 ...
- CSS下拉列表错误纠正
上一篇关于CSS制作下来列表的错误纠正. 在上一篇中,用CSS只做了下拉列表,但是鼠标不放在导航栏上的时候,下拉列表也是出来的.具体错误就是 div ul{ list-style:none; max- ...
- C# winform 若要在加载设计器前避免可能发生的数据丢失,必须纠正以下错误
winform中有时添加了新控件之后编译会报错: 若要在加载设计器前避免可能发生的数据丢失,必须纠正以下错误,如图: 解决方案: 1.“解决方案”→“批生成”→“清理”→“确定”: 2.“解决方案”→ ...
- JAVA classpath, 纠正我一直以来错误的认知
如何调在CLI中使用java tool(JDK中的java命令)调用一个打包在jar中的类,我想大多数人都能给出笼统的方案: java -classpath xxxxx com.test.classA ...
- VS2008 由于应用程序配置不正确,应用程序未能启动。重新安装应用程序可能会纠正这个问题。
提示这个错误,自己的程序是在VS2008下编译的C/C++ win32程序,自己当时在win7上开发测试,都没有问题,正常使用,也在另一台xp系统上也试了,都没有问题.就发给客户了,没想到有些客户竟然 ...
- 关闭 Mac 拼写自动纠正与横线转换
如果你是个程序员, 如果你恰好用 mac 自带的 notes 来做笔记, 很大可能性, 你会在里面贴代码, 但是, Mac 的拼写检查和自动纠正功能,会把代码变成你不想要的样子, 比如, 它会为你首字 ...
- 命令纠正工具 thefuck 的简单使用
在unix系列的系统中,总会出现 命令拼写或者执行错误的情况, 比如 把 python 写成了pythou, cd 到一个不存在的目录,执行任务的权限 不够的问题, 这是心里 总是 在 fuck,但是 ...
- java 英文单词拼写纠正框架(Word Checker)
Word Checker 本项目用于单词拼写检查. 项目简介 word checker 用于单词拼写检查. Github 地址 特性说明 支持 i18n 错误提示支持 i18N 支持英文的单词纠错 可 ...
- Noisy Channel模型纠正单词拼写错误
本文介绍 Stanford<From Languages to Information>课程中讲到的 单词拼写错误 纠正.背后的数学原理主要是贝叶斯公式.单词拼写错误纠正主要涉及到两个模型 ...
随机推荐
- Ubuntu 彻底卸载 MySQL 数据库
Ubuntu 18.04 彻底卸载MySQL 5.7.31 1. 查看MySQL的依赖项 dpkg --list|grep mysql 2. 卸载 mysql-common sudo apt remo ...
- python 多行对应元素求和
今天有个统计需求,需要对应的元素的列求和,文件示例如下: 1 ID1 0 2 7 2 ID2 1 5 6 3 ID3 2 2 6 4 ID4 1 6 0 5 ID2 3 8 3 6 ID2 0 8 3 ...
- 日常Java 2021/10/12
封装 在面向对象程式设计方法中,封装是指-种将抽象性函式接口的实现细节部分包装.隐藏起来的方法 封装可以被认为是一个保护屏障,防止该类的代码和数据被外部类定义的代码随机访问 要访问该类的代码和数据,必 ...
- day29并发编程
day29并发编程 1.进程锁 一.使用锁维护执行顺序 代码: from multiprocessing import Process,Lock import os import time def t ...
- 大数据学习day28-----hive03------1. null值处理,子串,拼接,类型转换 2.行转列,列转行 3. 窗口函数(over,lead,lag等函数) 4.rank(行号函数)5. json解析函数 6.jdbc连接hive,企业级调优
1. null值处理,子串,拼接,类型转换 (1) 空字段赋值(null值处理) 当表中的某个字段为null时,比如奖金,当你要统计一个人的总工资时,字段为null的值就无法处理,这个时候就可以使用N ...
- 100个Shell脚本—【脚本6】拷贝目录
[脚本6]拷贝目录 编写shell脚本,把/root/目录下的所有目录(只需要一级)拷贝到/tmp/目录下: 一.脚本 #!/bin/bash cd /root list=(`ls`) for i i ...
- Oracle中的null与空字符串''的区别
含义解释:问:什么是NULL?答:在我们不知道具体有什么数据的时候,也即未知,可以用NULL,我们称它为空,ORACLE中,含有空值的表列长度为零.ORACLE允许任何一种数据类型的字段为空,除了以下 ...
- 转 Android Studio中Junit调试
转:https://blog.csdn.net/xanthus_li/article/details/54314189 在程序开发完成后,需要交给专业的调试人员进行相关的专业调试(白盒测试,黑盒测试, ...
- 【Git项目管理】Git分支 - 远程分支
远程分支 远程引用是对远程仓库的引用(指针),包括分支.标签等等. 你可以通过 git ls-remote (remote) 来显式地获得远程引用的完整列表,或者通过 git remote show ...
- @RequestBody配合@Valid 校验入参参数
自定义一个Controller import com.example.demo.pojo.User; import org.springframework.web.bind.annotation.Po ...