一、异常
异常,就是不正常。说句直白的,就是程序的运行结果不在预期的结果范围内。在前面的相关分析中,个人的观点是严格限定使用异常。因为在C++这种编程语言中,对异常相关信息的处理有各种的限定条件:
- 兼容性和可移植性
C++应用的不同平台(Linux、Windows等)、不同编译器特别是不同硬件平台上细节兼容性的处理,都使得异常的应用受到限制。特别是C++和C语言经常混合编程,而C语言不存在异常机制,所以异常机制在这种场景下几乎难于展开应用 - 性能开销
异常机制处理的复杂性往往导致程序整体性能上的降低,而这个恰恰是C++应用的重点 - 异常编程和维护的复杂度
为了保证异常出现后的整体的资源安全性,就需要开发者通盘考虑,增加了开发者的负担;同时,异常机制会引入相关的异常信息,这会导致编译后整体目标的大小增加,这在一些特定的场景下,无法被接受 - 错误处理的兼容性
开发者都知道,在C++应用的场景中,错误和异常处理的机制非常多,开发者往往是混合在一起应用,这就导致了异常机制的全面铺开有了限制 - 结果的确定性
在C++应用的某些场景下,其要求结果必须返回准确的结果,从而保证程序运行的稳定性进而保障系统整体运行的稳定性,但异常却无法保证这种情况
通过上面的分析,其实大家很容易理解为什么在C++语言中异常机制并没有被普遍应用的原因。当然,异常机制在C++中目前的争议非常大。作为一种过渡语言,往往希望有高级语言的特性又想着兼容低级语言的特性。所以,C++中异常机制有争议是必然的结果。
二、异常的应用
那么在什么情况下可以考虑使用异常机制呢?
- 业务层应用
比如在上层的业务操作中,有机会的尽量可能使用异常机制;在单纯C++应用中的数据库处理应用中;对性能要求不高的应用场景等等。相反,在一些底层的逻辑特别是与系统交互的模块中,就要尽量避免使用异常机制 - 内存应用的场景
比如内存的越界甚至是OOM等,用异常可更清楚的表述相关信息 - 其它特定场景
如上层UI开发,相关库提供了异常机制等等。
另外可以通过下面的原则来控制使用异常机制:
- 降低异常处理的范围大小
也就是降低异常控制范围的颗粒度,不能大而化之的把整体的业务都try…catch中去 - 合理的利用异常开发
这个意思就是说即使可以使用异常机制也不能随意的使用,比如在循环中如何使用try catch机制,如何正确的匹配throw和catch等等。而一般对文件操作就不建议使用异常机制(这也得看调用的平台是否提供了何种机制) - 封闭异常控制范围
即解决好异常控制的边界,不能将异常无限制的应用,特别是跨设计单元(如层、模块等等)的范围
三、例程
根据前面的分析说明,看一下相关的例程:
#include <iostream>
#include <stdexcept>
void noExceptionTest() noexcept { std::cout << "Will not cause any exception!" << std::endl; }
void testException(int value) {
if (value < 10) {
throw std::invalid_argument("num less than 10");
}
if (value > 10) {
throw std::out_of_range("num greater than 10");
}
std::cout << "cur value is: " << value << std::endl;
}
int main() {
try {
testException(3); // exception
testException(16); // Cannot run to this location
} catch (const std::invalid_argument &e) {
std::cout << "exception caused by 3 : " << e.what() << std::endl;
} catch (const std::out_of_range &e) {
std::cout << "caused by 16: " << e.what() << std::endl;
} catch (const std::exception &e) {
std::cout << "std exception: " << e.what() << std::endl;
} catch (...) {
std::cout << "Unknown exception." << std::endl;
}
return 0;
}
异常相关的例程比较简单,大家就能明白怎么代码的意思。
四、如何正确使用noexcept
在C++11后,提供了noexcept这个关键字,那么如何正确利用其来控制异常的应用呢?
- C++中显示不允许抛出异常的位置
典型的如析构函数、移动操作以及constexpr控制(有版本限制),还有Swap操作等等 - 平台相关的接口调用
比如操作系统的一些信号处理操作以及相关的调用 - 明确指定必须返回结果的场景
在一些业务场景中,要求无论何种情况下都必须有结果返回,而不允许抛出异常;或者意外情况导致程序直接退出等等。 - 其它一些情况
在其它一些已经显式指定可以不用抛出异常的场景下,都可以使用noexcept
五、总结
技术的应用最主要的是选择合适的场景,这样才能把技术的优势展现出来。正如庖丁解牛里说的,“以无厚入有间,恢恢乎其于游刃必有余地矣”。一个优秀的开发者,其实就是需要把技术彻底的吃透,这样才能把技术与实践有机的融合。

16万+

被折叠的 条评论
为什么被折叠?



