没有合适的资源?快使用搜索试试~ 我知道了~
首页C++进阶指南:告别C习惯,探索C++新特性
"Efficient C++中文版是一本针对C++编程的深入指南,特别是对于那些已经熟悉C语言但需要过渡到C++的程序员。该书强调了C++与C之间的差异,以及如何有效地利用C++的新特性。C++相较于C语言,增加了许多高级功能,如私有和保护成员、函数重载、缺省参数、构造和析构函数、自定义操作符、内联函数、引用、友元、模板、异常处理和命名空间等,提供了更大的设计灵活性。 作者提倡在C++编程中优先使用const和inline而非#define,以避免预处理器带来的问题。这是因为预处理器宏可能导致符号名在编译过程中被替换,导致错误难以追踪,且在调试阶段也不易显示真实名称。通过使用const和inline,程序员可以明确地表示变量或函数的不变性,并提高代码的可读性和维护性。然而,需要注意的是,定义指针常量时,不仅指向的对象要声明为const,指针本身也需要是const,以便在头文件中正确地进行常量引用。 在面对C++的众多选项时,尽管初学者可能会感到困惑,但遵循这些原则有助于确保代码的正确性和一致性。C++程序员应学会利用其丰富的特性,同时克服那些不符合C++精神的传统习惯,以提升编程效率和代码质量。本书不仅适合希望深入学习C++的读者,也适合那些希望改进现有C技能并适应C++新特性的程序员。"
资源详情
资源推荐
operator new 在无法完成内存分配请求时会抛出异常(以前的做法一般是返
回 0,一些旧一点的编译器还这么做。你愿意的话也可以把你的编译器设置成
这样。关于这个话题我将推迟到本条款的结尾处讨论)。大家都知道,处理内存
不够所产生的异常真可以算得上是个道德上的行为,但实际做起来又会象刀架
在脖子上那样痛苦。所以,你有时会不去管它,也许一直没去管它。但你心里
一定还是深深地隐藏着一种罪恶感:万一 new真的产生了异常怎么办?
你会很自然地想到处理这种情况的一种方法,即回到以前的老路上去,使
用预处理。例如,C 的一种常用的做法是,定义一个类型无关的宏来分配内存
并检查分配是否成功。对于 C++来说,这个宏看起来可能象这样:
#define NEW(PTR, TYPE) \
try { (PTR) = new TYPE; } \
catch (std::bad_alloc&) { assert(0); }
“慢!std::bad_alloc 是做什么的?”你会问。bad_alloc 是 operator new 不能
满足内存分配请求时抛出的异常类型,std 是 bad_alloc 所在的名字空间(见条
款 28)的名称。“好!”你会继续问,“assert 又有什么用?”如果你看看标准 C
头文件<assert.h>(或与它相等价的用到了名字空间的版本<cassert>,见条款
49),就会发现 assert 是个宏。这个宏检查传给它的表达式是否非零,如果不
是非零值,就会发出一条出错信息并调用 abort。assert 只是在没定义标准宏
NDEBUG 的时候,即在调试状态下才这么做。在产品发布状态下,即定义了
NDEBUG 的时候,assert 什么也不做,相当于一条空语句。所以你只能在调试
时才能检查断言(assertion))。
NEW 宏不但有着上面所说的通病,即用 assert 去检查可能发生在已发布
程序里的状态(然而任何时候都可能发生内存不够的情况),同时,它还在 C++
里有另外一个缺陷:它没有考虑到 new 有各种各样的使用方式。例如,想创建
类型 T 对象,一般有三种常见的语法形式,你必须对每种形式可能产生的异常
都要进行处理:
new T;
new T(constructor arguments);
new T[size];
这里对问题大大进行了简化,因为有人还会自定义(重载)operator new,所
以程序里会包含任意个使用 new 的语法形式。
那么,怎么办?如果想用一个很简单的出错处理方法,可以这么做:当内
存分配请求不能满足时,调用你预先指定的一个出错处理函数。这个方法基于
一个常规,即当 operator new 不能满足请求时,会在抛出异常之前调用客户指
定的一个出错处理函数——一般称为 new-handler 函数。(operator new 实际工
作起来要复杂一些,详见条款 8)
指定出错处理函数时要用到 set_new_handler 函数,它在头文件<new>里
大致是象下面这样定义的:
typedef void (*new_handler)();
new_handler set_new_handler(new_handler p) throw();
可以看到,new_handler 是一个自定义的函数指针类型,它指向一个没有
输入参数也没有返回值的函数。set_new_handler 则是一个输入并返回
new_handler 类型的函数。
set_new_handler 的输入参数是 operator new 分配内存失败时要调用的出
错处理函数的指针,返回值是 set_new_handler 没调用之前就已经在起作用的
旧的出错处理函数的指针。
可以象下面这样使用 set_new_handler:
// function to call if operator new can't allocate enough memory
void noMoreMemory()
{
cerr << "Unable to satisfy request for memory\n";
abort();
}
int main()
{
set_new_handler(noMoreMemory);
int *pBigDataArray = new int[100000000];
...
}
假如 operator new 不能为 100,000,000 个整数分配空间,noMoreMemory
将会被调用,程序发出一条出错信息后终止。这就比简单地让系统内核产生错
误信息来结束程序要好。(顺便考虑一下,假如 cerr 在写错误信息的过程中要动
态分配内存,那将会发生什么...)
operator new 不能满足内存分配请求时,new-handler 函数不只调用一次,
而是不断重复,直至找到足够的内存。实现重复调用的代码在条款 8 里可以看
到,这里我用描述性的的语言来说明:一个设计得好的 new-handler 函数必须
实现下面功能中的一种。
产生更多的可用内存。这将使 operator new 下一次分配内存的尝试有可能
获得成功。实施这一策略的一个方法是:在程序启动时分配一个大的内存块,
然后在第一次调用 new-handler 时释放。释放时伴随着一些对用户的警告信息,
如内存数量太少,下次请求可能会失败,除非又有更多的可用空间。
安装另一个不同的 new-handler 函数。如果当前的 new-handler 函数不能
产生更多的可用内存,可能它会知道另一个 new-handler 函数可以提供更多的
资源。这样的话,当前的 new-handler 可以安装另一个 new-handler 来取代它(通
过调用 set_new_handler)。下一次 operator new调用 new-handler 时,会使用
最近安装的那个。(这一策略的另一个变通办法是让 new-handler 可以改变它自
己的运行行为,那么下次调用时,它将做不同的事。方法是使 new-handler 可
以修改那些影响它自身行为的静态或全局数据。)
卸除 new-handler。也就是传递空指针给 set_new_handler。没有安装 new-
handler,operator new 分配内存不成功时就会抛出一个标准的 std::bad_alloc
类型的异常。
抛出 std::bad_alloc 或从 std::bad_alloc 继承的其他类型的异常。这样的异
常不会被 operator new 捕捉,所以它们会被送到最初进行内存请求的地方。(抛
出别的不同类型的异常会违反 operator new 异常规范。规范中的缺省行为是调
用 abort,所以 new-handler要抛出一个异常时,一定要确信它是从std::bad_alloc
继承来的。想更多地了解异常规范,参见条款 M14。)
没有返回。典型做法是调用 abort 或 exit。abort/exit 可以在标准 C 库中找
到(还有标准 C++库,参见条款 49)。
上面的选择给了你实现 new-handler 函数极大的灵活性。
处理内存分配失败的情况时采取什么方法,取决于要分配的对象的类:
class X {
public:
static void outOfMemory();
...
};
class Y {
public:
static void outOfMemory();
...
};
X* p1 = new X; // 若分配成功,调用 X::outOfMemory
Y* p2 = new Y; // 若分配不成功,调用 Y::outOfMemory
C++不支持专门针对于类的 new-handler 函数,而且也不需要。你可以自
己来实现它,只要在每个类中提供自己版本的 set_new_handler 和 operator
new。类的 set_new_handler 可以为类指定 new-handler( 就象标准的
set_new_handler 指定全局 new-handler 一样)。类的 operator new则保证为类
的对象分配内存时用类的 new-handler 取代全局 new-handler。
假设处理类 X 内存分配失败的情况。因为 operator new 对类型 X 的对象
分配内存失败时,每次都必须调用出错处理函数,所以要在类里声明一个
new_handler 类型的静态成员。那么类 X 看起来会象这样:
class X {
public:
static new_handler set_new_handler(new_handler p);
static void * operator new(size_t size);
private:
static new_handler currentHandler;
剩余303页未读,继续阅读
哈上的风景
- 粉丝: 0
- 资源: 3
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
- 计算机人脸表情动画技术发展综述
- 关系数据库的关键字搜索技术综述:模型、架构与未来趋势
- 迭代自适应逆滤波在语音情感识别中的应用
- 概念知识树在旅游领域智能分析中的应用
- 构建is-a层次与OWL本体集成:理论与算法
- 基于语义元的相似度计算方法研究:改进与有效性验证
- 网格梯度多密度聚类算法:去噪与高效聚类
- 网格服务工作流动态调度算法PGSWA研究
- 突发事件连锁反应网络模型与应急预警分析
- BA网络上的病毒营销与网站推广仿真研究
- 离散HSMM故障预测模型:有效提升系统状态预测
- 煤矿安全评价:信息融合与可拓理论的应用
- 多维度Petri网工作流模型MD_WFN:统一建模与应用研究
- 面向过程追踪的知识安全描述方法
- 基于收益的软件过程资源调度优化策略
- 多核环境下基于数据流Java的Web服务器优化实现提升性能
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功