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>课程中讲到的 单词拼写错误 纠正.背后的数学原理主要是贝叶斯公式.单词拼写错误纠正主要涉及到两个模型 ...
随机推荐
- 洛谷 P4887 -【模板】莫队二次离线(第十四分块(前体))(莫队二次离线)
题面传送门 莫队二次离线 mol ban tea,大概是这道题让我第一次听说有这东西? 首先看到这类数数对的问题可以考虑莫队,记 \(S\) 为二进制下有 \(k\) 个 \(1\) 的数集,我们实时 ...
- Latex 文档格式化
title: "Latex 文档格式化" author: 李龙翔 date: "Nov 22, 2019" subject: "Markdown&qu ...
- 【Pathview web】通路映射可视化
前言 pathview是一个通路可视化友好的R包,最主要的是它支持多组学数据映射(基因/蛋白-代谢).自己用过它的R包,后来发现有网页版的,果断介绍给学员.因为不常用,记录要点,以后温习备用. 目前w ...
- Nginx 动态增加扩展
Nginx 动态增加扩展 1. 先查看目前nginx已加载模块 /home/nginx-1.18.0 # nginx -V nginx version: nginx/1.18.0 built by g ...
- R语言与医学统计图形-【25】ggplot图形分面
ggplot2绘图系统--图形分面 ggplot2的分面faceting,主要有三个函数: facet_grid facet_wrap facet_null (不分面) 1. facet_grid函数 ...
- mysql—MySQL数据库中10位或13位时间戳和标准时间相互转换
1.字符串时间转10位时间戳 select FLOOR(unix_timestamp(create_time)) from page; #create_time为字段名 page为表名 eg:sele ...
- GISer如何突破二次开发瓶颈
年初时写的<一个GISer的使命>那篇文章中,提出了GISer的技术提升路径可以分为四个大的阶段: 阶段一,能使用商业GIS软件去解决问题. 阶段二,能使用开源GIS软件去解决问题. 阶段 ...
- 疯了吧!这帮人居然用 Go 写“前端”?(二)
作者 | 郑嘉涛(羣青) 来源|尔达 Erda 公众号 前言 上篇我们讲了故事发生的背景,也简单阐述了组件及协议的设想: 一.丰富的通用组件库. 二.组件渲染能力,将业务组件渲染成通用组件 ...
- 【leetcode】121. Best Time to Buy and Sell Stock(股票问题)
You are given an array prices where prices[i] is the price of a given stock on the ith day. You want ...
- Vue.js 学习
一,Vue.js 介绍 Vue 是一套用于构建用户界面的渐进式javascript框架,与其它大型框架不同的是:Vue被设计为可以自底向上逐层应用.Vue的核心库只关注视图层,不仅易于上手,还便于与第 ...