首页生活资讯正文

我为什么放弃C++,选择C语言编写个人项目。

2024-10-05 次浏览


【CSDN 编者按】一直以来,C 和 C++ 都长短常优秀的编程语言。不外,两种语言虽名称有些类似,但利用场景存在伟大的分歧。对付 C 语言而言,其主要被用于操作体系、容器、物联网、数据库等范畴的开发,而 C++ 则是开发桌面软件、图形处置、游戏、网站的最佳对象。在本文中,作者原认为 C++ 在开发根基举措措施时会更胜一筹,然而颠末与 C 语言的测验考试对照,发现事实并非如斯。

原文链接:https://250bpm.com/blog:4/?continueFlag=c778b3c9525d12a012a35269d830ebcc

我为什么放弃C++,选择C语言编写个人项目。
(图片来源网络,侵删)

声明:本文为 CSDN 翻译,转载需注明起源。

作者 | Martin Sústrik

译者 | 弯月 责编 | 屠敏

出品 | CSDN(ID:CSDNnews)

以下为翻译正文:

起首声明,在整个职业生活中,我一直在使用C++,并且在做年夜多半项目时,C++仍旧是我的首选语言。

是以,在开端构建小我项目ZeroMQ(可伸缩的散布式或并发利用法式设计的高机能异步新闻库)时,我也选用了C++,主要缘故原由如下:

C++包括一些数据布局和算法库。假如使用C语言,我将不得不依附第三方库,或者本身着手编写根本算法。

C++会强制我在编程作风上坚持一些根本的同一性。例如,this参数不容许使用几种分歧的机制将指针通报给正在处置的工具,而这个问题在C项目中很常见。同样,弗成以明白将成员变量标志为私有,此外还有C++的一些其他特性。

使用C语言实现虚函数异常繁杂,会导致懂得和治理代码的难度加剧。不外,严厉来说,这个问题实在是上一个问题的一个子集,但我感到有需要零丁指出。

末了,每小我都喜欢在代码的末端主动挪用析构函数。

然而,事到现在,我不得不认可C++是一个糟糕的选择。下面,我来解释一下缘故原由。

起首,我的小我项目ZeroMQ是一个连续运行的根基举措措施,永久不该该出故障,永久不该该表示出不决义的行动。是以,差错处置至关紧张,必需做到明白且严厉。

然而,C++的非常处置并不克不及满意我的需求。假如法式不会失足,那么选择C++没有任何问题,只需将main函数包装在try/catch中,集中在一个处所处置所有差错。

假如你的目的是保证不会呈现不决义的行动,那么C++的非常处置就会酿成一场恶梦。因为C++解耦了非常的产生与处置,是以差错处置异常容易,但也造成了你险些弗成能保证法式永久不会运行不决义的行动。

在C语言中,差错的发生和处置是慎密联合的,在统一块源代码中。是以,在失足时很容易懂得产生了什么:


int rc = fx ();if (rc != 0)handle_error ();

而在C++中,你只能抛失足误,却不清晰毕竟产生了什么:


int rc = fx ();if (rc != 0)throw std::exception ();

问题在于,你并不清晰在哪里处置非常。处置差错的代码在统一个函数中会加倍便利懂得,只管不太便利浏览:


try {int rc = fx ();if (rc != 0)throw std::exception ("大众Error!"大众);catch (std::exception &e) {handle_exception ();

然而,我们来斟酌统一个函数抛出两个分歧的差错,成果会怎么样:


class exception1 {};class exception2 {};try {if (condition1)throw my_exception1 ();if (condition2)throw my_exception2 ();catch (my_exception1 &e) {handle_exception1 ();catch (my_exception2 &e) {handle_exception2 ();

以下是等效的C代码:


if (condition1)handle_exception1 ();if (condition2)handle_exception2 ();

相较之下,C语言加倍便利浏览,并且编译器也会天生更高效的代码。

然而,C++的问题还不仅限于此。斟酌某个函数会激发非常,但不会处置非常的环境。在这种环境下,差错的处置可以放到任何处所,详细取决于从哪里挪用该函数。

针对分歧的环境,采纳分歧的方式处置非常。这种办法听起来彷佛很有事理,但很快就会酿成一场恶梦。

在修复某个Bug时,你会发现很多其他处所也有雷同的Bug,由于它们都复制了统一段差错处置代码。每当添加一个函数挪用,就有可能增长一个新非常,假如挪用函数的代码没有妥当处置该非常,就意味着增长了一个新Bug。

假如你还想保持“没有不决义的行动”原则,就不得不引入新非常,以便区分分歧的故障模式。然则,添加新非常就意味着,它会上升到分歧的处所。你必需在所有处所添加响应的非常处置,不然就会呈现不决义的行动。

看到这里,你可能想说:这便是非常的正确用法啊。

然而问题在于,非常只是一个对象,目标是用更体系的方式治理出现指数增加的差错处置代码,但它并不克不及办理基本的问题。乃至可以说,非常有可能导致环境恶化,由于你不仅必要编写新的非常类型,还必要针对新类型编写非常处置代码。

斟酌到上述问题,我决议使用C++,但不使用非常。现在我的这个项目便是如许实现的。

不幸的是,问题并没有就此止步……

斟酌一下,假如工具的初始化失败,会产生什么。构造函数没有返回值,是以只能经由过程抛出非常来申报失败。然则,我决议不使用非常。以是,我们必需像下面如许处置:


class foopublic:foo ();int init ();

在创立实例时,会挪用构造函数(这个函数不会失败),然后挪用init函数(这个函数可能会失败)。

与C语言相比,C++代码更繁杂:


struct fooint foo_init (struct foo *self);

然而,C++代码真正的问题在于,假如开发职员在构造函数中编写一些代码,会产生什么。

在这种环境下,会呈现一个特殊的新工具状况。因为工具已构造,但尚未挪用init函数,是以是“半初始化”状况。我们应该改动工具(分外是析构函数)来处置这个新状况。这意味着,给每个办法添加新前提。

有人可能想说,这还不是由于你工资地添加了不使用非常的限定。。假如构造函数中抛出非常,C++运行时会正确地清算工具,不会呈现“半初始化”状况。

话虽如斯,然而问题在于,假如使用非常,如上所述,就必需处置所有与非常相关的繁杂性。对付一个必要在遇到故障时表示出优秀的硬朗性的根基举措措施组件来说,这不是一个合理的选择。

此外,纵然初始化没有问题,工具的烧毁也绝对会遇到问题。你不克不及在析构函数中抛出非常。这可不是我强加的工资限定,而是由于假如在过程中挪用析构函数,或者规复栈时正好抛出非常,就会导致整个过程瓦解。

是以,假如烧毁可能失败,你就必要两个零丁的函数来处置它:


class foopublic:int term ();~foo ();

这就遇到了与初始化雷同的问题:一个“半终止”状况,我们必需以某种方式处置,向各个成员函数添加新前提。


class foopublic:foo () : state (semi_initialised)int init ()if (state != semi_initialised)handle_state_error ();state = intitialised;int term ()if (state != initialised)handle_state_error ();state = semi_terminated;~foo ()if (state != semi_terminated)handle_state_error ();int bar ()if (state != initialised)handle_state_error ();

与之相比,C语言的代码如下。此中只有两种状况。未初始化工具/内存,我们无需担忧上述问题,并且布局可以包括随意率性数据。并且只要工具进入已初始化的状况,就可以正常事情。是以,工具中不必要状况机:


struct fooint foo_init ()int foo_term ()int foo_bar ()

斟酌一下,假如在上述代码中添加承继,会产生什么。C++容许将基类初始化为派生类构造函数的一部门。假如抛出非常,就会破坏已胜利初始化的工具:


class foo : public barpublic:foo () : bar () {}

然而,一旦引入零丁的init函数,状况的数目就会开端增加。除了未初始化、半初始化、初始化和半终止状况之外,你还会遇到这些状况的组合。你可以想象一个基类已完全初始化、但派生类半初始化的工具。

对付如许的工具,险些弗成能确保其行动不出问题。工具的半初始化和半终止部门有许多分歧的组合,而且鉴于它们只在异常罕有的环境下才会激发故障,是以年夜多半相关代码可能未经测试就进入了临盆。

综上所述,我以为,假如你的需求是不容许呈现不决义的行动,则不得当面向工具的编程。这个问题不仅限于C++,任何具有构造函数和析构函数的面向工具语言都不得当。

是以,更得当面向工具语言的项目是:对开发速率有要求、但对“不存在不决义的行动”没有太高要求。

这个问题没有灵丹灵药。体系编程选择C语言更为适宜。

C++处置函数
关于雪的朋友圈文案 汽车车灯图解大全
相关内容