如果你的目标是保证不会出现未定义的行为,那么C++的异常处理就会变成一场噩梦。由于C++解耦了异常的发生与处理,因此错误处理非常容易,但也造成了你几乎不可能保证程序永远不会运行未定义的行为。 ...
我为什么放弃 C++,选择 C 语言编写个人项目?首先声明,在整个职业生涯中,我一直在使用C++,而且在做大多数项目时,C++仍然是我的首选语言。 因此,在开始构建个人项目ZeroMQ(可伸缩的分布式或并发应用程序设计的高性能异步消息库)时,我也选用了C++,主要原因如下:
然而,事到如今,我不得不承认C++是一个糟糕的选择。下面,我来解释一下原因。 首先,我的个人项目ZeroMQ是一个持续运行的基础设施,永远不应该出故障,永远不应该表现出未定义的行为。因此,错误处理至关重要,必须做到明确且严格。 然而,C++的异常处理并不能满足我的需求。如果程序不会出错,那么选择C++没有任何问题,只需将main函数包装在try/catch中,集中在一个地方处理所有错误。 如果你的目标是保证不会出现未定义的行为,那么C++的异常处理就会变成一场噩梦。由于C++解耦了异常的发生与处理,因此错误处理非常容易,但也造成了你几乎不可能保证程序永远不会运行未定义的行为。 在C语言中,错误的产生和处理是紧密结合的,在同一块源代码中。因此,在出错时很容易理解发生了什么:
而在C++中,你只能抛出错误,却不清楚究竟发生了什么:
问题在于,你并不清楚在哪里处理异常。处理错误的代码在同一个函数中会更加方便理解,尽管不太方便阅读:
然而,我们来考虑同一个函数抛出两个不同的错误,结果会怎么样:
以下是等效的C代码:
相较之下,C语言更加方便阅读,而且编译器也会生成更高效的代码。 然而,C++的问题还不仅限于此。考虑某个函数会引发异常,但不会处理异常的情况。在这种情况下,错误的处理可以放到任何地方,具体取决于从哪里调用该函数。 针对不同的情况,采用不同的方式处理异常?这种方法听起来似乎很有道理,但很快就会变成一场噩梦。 在修复某个Bug时,你会发现许多其他地方也有相同的Bug,因为它们都复制了同一段错误处理代码。每当添加一个函数调用,就有可能增加一个新异常,如果调用函数的代码没有妥善处理该异常,就意味着增加了一个新Bug。 如果你还想坚持“没有未定义的行为”原则,就不得不引入新异常,以便区分不同的故障模式。但是,添加新异常就意味着,它会上升到不同的地方。你必须在所有地方添加相应的异常处理,否则就会出现未定义的行为。 看到这里,你可能想说:这就是异常的正确用法啊? 然而问题在于,异常只是一个工具,目的是用更系统的方式管理呈现指数增长的错误处理代码,但它并不能解决根本的问题。甚至可以说,异常有可能导致情况恶化,因为你不仅需要编写新的异常类型,还需要针对新类型编写异常处理代码。 考虑到上述问题,我决定使用C++,但不使用异常。如今我的这个项目就是这样实现的。 不幸的是,问题并没有就此止步…… 考虑一下,如果对象的初始化失败,会发生什么?构造函数没有返回值,因此只能通过抛出异常来报告失败。但是,我决定不使用异常。所以,我们必须像下面这样处理:
近期文章
推荐阅读
热门问答
|
0