肾结石挂什么科室| 生理需求是什么意思| 什么样的小手| 牛油果和什么不能一起吃| 夏天吃什么蔬菜| 蒙圈什么意思| 太容易出汗是什么原因| 生肖猪和什么生肖最配| 查宝宝五行八字缺什么| 倒数第二颗牙齿叫什么| 怎么判断脸上是什么斑| 淋病和梅毒有什么区别| 手脚浮肿是什么原因引起的| 于是什么意思| 一个虫一个夫念什么| 萎谢是什么意思| 1993属什么生肖| 女票什么意思| 什么样才是包皮| 06属什么生肖| 咳嗽想吐是什么原因| 炖肉什么时候放盐| 得瑟什么意思| 女人总犯困是什么原因| 鹅吃什么草| 腰痛去医院挂什么科| 喉咙痛吃什么饭菜好| 什么食物对眼睛视力好| 玄色是什么颜色| 手为什么会发麻| nmr是什么意思| 九月三日是什么纪念日| 贝的偏旁有什么字| 什么是谈恋爱| 素描是什么意思| 要强是什么意思| 六月初九是什么星座| 象牙带身上有什么好处| fw什么意思| 谷草转氨酶偏高是什么意思| 高祖父的爸爸叫什么| 葵花宝典是什么意思| 叶酸是什么维生素| 肝囊肿吃什么食物好| 苦荞茶喝了有什么好处| 走青是什么意思| 怕热是什么体质| 女人左眼跳是什么预兆| 老鼠疮是什么病| 一个木一个舌读什么| 心绞痛什么症状| 眼睛眼屎多是什么原因| 不适是什么意思| 为什么空调| 总咳嗽是什么原因| 梦见大房子是什么预兆| 喝酒容易醉是什么原因| 梦见自己流鼻血是什么预兆| 大白菜什么时候种| 牵牛花为什么叫牵牛花| 主任科员是什么级别| 膈是什么器官| 女人为什么会患得患失| 翡翠a货是什么意思| 口水多是什么原因引起的| 骨折有什么忌口| 吃什么瘦肚子| 梦见剪头发预示什么| 盎司是什么意思| 男人很man是什么意思| 道场是什么意思| 男人早泄吃什么药最好| trans什么意思| 床头朝什么方向是正确的| 7月出生是什么星座| 喝蛋白粉有什么副作用| 老年痴呆症又叫什么名字| 死板是什么意思| 白带过氧化氢阳性什么意思| 脑供血不足吃什么中成药好| rbc是什么意思医学| 乳糜血是什么意思| 回民不能吃什么| 九月初十是什么星座| 再三的意思是什么| 梦见自己请客吃饭是什么意思| 什么是高潮| 月经来潮是什么意思| 人死后为什么要盖住脸| 耳道炎是什么原因引起的| 猜忌是什么意思| 冰室是什么意思| 为什么坐久了屁股疼| 衣锦还乡是什么意思| 肠胃消化不好吃什么食物| 腱鞘炎去医院挂什么科| 2009属什么生肖| 塑料是什么材料| 一什么便什么造句| kinghome是什么牌子| 古灵精怪什么意思| y是什么元素| 三七是什么意思| 抗体是什么| 尘肺病吃什么能排出尘| 寒风吹起细雨迷离是什么歌| 兆以上的计数单位是什么| 戌是什么生肖| 清五行属什么| 副产品是什么意思| 什么人骗别人也骗自己| 二级以上医院是什么意思| 比围是什么| 代理是什么| 开小灶是什么意思| 朗姆酒兑什么好喝| 拐子是什么鱼| 滚床单是什么意思| 猪和什么生肖最配| 大学是什么学历| 布洛芬治什么| 什么是对的人| 花生死苗烂根用什么药| 白带黄吃什么药| guess是什么牌子| 舌苔白有齿痕吃什么药| 酸菜鱼一般加什么配菜| 月经期间喝什么好排毒排污血| 1993年出生的属什么| 季昌明是什么级别| 咳嗽喝什么饮料| 什么是帽子戏法| 尿隐血阳性是什么病| 等边三角形又叫什么三角形| 婴儿胎发什么时候剪最好| 牛子是什么意思| 一键挪车什么意思| 为什么英文怎么说| 草莓是什么季节的水果| 怀孕十天左右有什么反应| 怎么看自己五行属什么| who医学上是什么意思| 降钙素原检测是查什么的| 10月10号是什么星座| 梦到怀孕生孩子是什么意思| 中秋节是什么时候| 梦见河水是什么意思| 和田玉五行属什么| 贱货是什么意思| 高职本科什么意思| 冬天怕冷夏天怕热是什么原因| 4.25是什么星座| 白鸭是什么鸭| 相思病是什么意思| 货值是什么意思| 金可以组什么词| 八月十五是什么节日| 韩愈字什么| 玉米吃了有什么好处| 蓓字五行属什么| 拉肚子吃什么药好使| 今年26岁属什么生肖| 眼睛发炎用什么眼药水| 3月3是什么星座| 舌苔厚白应该吃什么| 直径是什么| 梅毒是什么意思| ds是什么意思| 拉肚子喝什么药| 阴唇为什么一个大一个小| 美容行业五行属什么| 东盟为什么没有中国| 生理期提前是什么原因| 湖北九头鸟是什么意思| 男人左手麻木什么原因| 伤口溃烂不愈合用什么药| 什么属相不能养龙鱼| 跑步大腿痒是什么原因| cla是什么| 乙酰氨基葡萄糖苷酶阳性什么意思| 大象是什么颜色| 便秘是什么引起的| 软件测试需要学什么| 脑供血不足用什么药| 宫颈多发纳囊是什么病| 卸磨杀驴什么意思| 醋精是什么| 带状疱疹能吃什么| 宋朝之后是什么朝代| 子宫内膜2mm说明什么| 白领是什么意思| 成服是什么意思| 司南是什么| 怀孕了梦见蛇是什么意思| 夫妻宫是什么意思| 小孩拉肚子吃什么药效果好| 阴毛瘙痒是什么原因| 篱笆是什么| 空气棉是什么面料| 今日立冬吃什么| 月经每次都推迟是什么原因| 减肥医院挂什么科| 溃疡是什么意思| 竞走是什么意思| 眼睛痛用什么药| freeze是什么意思| 清洁度iv是什么意思| 生物工程专业学什么| 江苏有什么山| 教学相长是什么意思| 培育是什么意思| 做梦梦到牛是什么意思| 月子早餐吃什么好| 睡觉出汗是什么原因男性| 猪横脷是什么| 胃炎吃什么药效果最好| 丑时属什么| 咳嗽有黄痰是什么原因| 哺乳期可以吃什么水果| 碧霄是什么意思| 踏马什么意思| 支气管炎吃什么药效果最好| 姑息是什么意思| 什么是电解质饮料| 什么是dna| 谷丙转氨酶偏高说明什么原因| 前庭功能检查是查什么| 什么是中线| 姨妈期不能吃什么| 排骨炖什么汤好喝| 可可粉是什么东西| 进贡是什么意思| 自然数的定义是什么| 生物酶是什么东西| 脂肪肝应注意什么| 胎位不正是什么原因导致的| 老咳嗽是什么原因| 什么奶粉跟母乳一个味| 浓郁是什么意思| 生肖排第六是什么生肖| 宜昌有什么特产| 随波逐流什么意思| 硬不起来吃什么好| 鹅蛋炒香菜治什么病| 为什么挠脚心会痒| 阴道口痒是什么原因| 右眼皮一直跳什么预兆| 尿酸高尿液是什么颜色| 头晕目赤是什么意思| 斋醮是什么意思| 肋骨骨折挂什么科| 今年什么时间进伏| 干眼症吃什么药好| 甲状腺功能是什么| 两特两重指的是什么| 冰丝纤维是什么面料| 庄周梦蝶是什么意思| 阴虚火旺吃什么食物| 荷尔蒙是什么东西起什么作用| 向内求什么意思| 淋巴细胞比率偏高是什么原因| 什么车最长| 九月二十二是什么星座| 猴戏是什么意思| 百度
这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 ? 论坛首页 ? 嵌入式开发 ? 软件与操作系统 ? 系统编程选择C语言更为合适

共14条 1/2 1 2 跳转至

系统编程选择C语言更为合适

工程师
2025-08-06 23:27:18     打赏
百度 吴诗展说。

以下为翻译正文:

首先声明,在整个职业生涯中,我一直在使用C++,而且在做大多数项目时,C++仍然是我的首选语言。

因此,在开始构建个人项目ZeroMQ(可伸缩的分布式或并发应用程序设计的高性能异步消息库)时,我也选用了C++,主要原因如下:

  1. C++包含一些数据结构和算法库。如果使用C语言,我将不得不依赖第三方库,或者自己动手编写基本算法。

  2. C++会强制我在编程风格上保持一些基本的统一性。例如,this参数不允许使用几种不同的机制将指针传递给正在处理的对象,而这个问题在C项目中很常见。同样,不可以明确将成员变量标记为私有,此外还有C++的一些其他特征。

  3. 使用C语言实现虚函数非常复杂,会导致理解和管理代码的难度加剧。不过,严格来说,这个问题其实是上一个问题的一个子集,但我觉得有必要单独指出。

  4. 最后,每个人都喜欢在代码的末尾自动调用析构函数。

然而,事到如今,我不得不承认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 foo
{
public:
foo ();
int init ();
...
};

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

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

struct foo
{
...
};
int foo_init (struct foo *self);

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

在这种情况下,会出现一个特殊的新对象状态。由于对象已构造,但尚未调用init函数,因此是“半初始化”状态。我们应该修改对象(特别是析构函数)来处理这个新状态。这意味着,给每个方法添加新条件。

有人可能想说,这还不是因为你人为地添加了不使用异常的限制?!如果构造函数中抛出异常,C++运行时会正确地清理对象,不会出现“半初始化”状态。

话虽如此,然而问题在于,如果使用异常,如上所述,就必须处理所有与异常相关的复杂性。对于一个需要在遇到故障时表现出优秀的健壮性的基础设施组件来说,这不是一个合理的选择。

此外,即使初始化没有问题,对象的销毁也绝对会遇到问题。你不能在析构函数中抛出异常。这可不是我强加的人为限制,而是因为如果在进程中调用析构函数,或者恢复栈时恰好抛出异常,就会导致整个进程崩溃。

因此,如果销毁可能失败,你就需要两个单独的函数来处理它:

class foo
{
public:
...
int term ();
~foo ();
};

这就遇到了与初始化相同的问题:一个“半终止”状态,我们必须以某种方式处理,向各个成员函数添加新条件。

class foo
{
public:
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 foo
{
...
};
int foo_init ()
{
...
}
int foo_term ()
{
...
}
int foo_bar ()
{
...
}

考虑一下,如果在上述代码中添加继承,会发生什么。C++允许将基类初始化为派生类构造函数的一部分。如果抛出异常,就会破坏已成功初始化的对象:

class foo : public bar
{
public:
foo () : bar () {}
...
};

然而,一旦引入单独的init函数,状态的数量就会开始增长。除了未初始化、半初始化、初始化和半终止状态之外,你还会遇到这些状态的组合。你可以想象一个基类已完全初始化、但派生类半初始化的对象。

对于这样的对象,几乎不可能确保其行为不出问题。对象的半初始化和半终止部分有很多不同的组合,并且鉴于它们只在非常罕见的情况下才会引发故障,因此大多数相关代码可能未经测试就进入了生产。

综上所述,我认为,如果你的需求是不允许出现未定义的行为,则不适合面向对象的编程。这个问题不仅限于C++,任何具有构造函数和析构函数的面向对象语言都不适合。

因此,更适合面向对象语言的项目是:对开发速度有要求、但对“不存在未定义的行为”没有太高要求。

这个问题没有灵丹妙****。系统编程选择C语言更为合适。




专家
2025-08-06 23:38:47     打赏
2楼

谢谢分享


工程师
2025-08-06 23:28:21     打赏
3楼

讲解的还是比较到位的


专家
2025-08-06 23:30:01     打赏
4楼

谢谢分享


专家
2025-08-06 11:07:27     打赏
5楼

总结的还是比较好的


高工
2025-08-06 22:21:17     打赏
6楼

感谢分享


工程师
2025-08-06 23:55:56     打赏
7楼

讲解的非常好


院士
2025-08-06 08:11:06     打赏
8楼

谢谢楼主的分享~!


专家
2025-08-06 08:30:39     打赏
9楼

谢谢分享


院士
2025-08-06 08:32:49     打赏
10楼

感谢分享


共14条 1/2 1 2 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]
小狗肚子里有虫子吃什么药 serum是什么意思 胃肠道功能紊乱吃什么药 安宫丸什么时候吃 居住证有什么用
知柏地黄丸治疗什么病 aq是什么标准 嘴唇痒边缘痒用什么药 解析是什么意思 什么人容易得甲亢
知见是什么意思 56个民族都有什么族 背道而驰是什么意思 手术拆线挂什么科 晚上2点是什么时辰
脑内多发缺血灶是什么意思 大拇指指甲凹陷是什么原因 喝酒尿多是什么原因 吃什么可以变胖 刘亦菲为什么不结婚
发端是什么意思hcv9jop1ns7r.cn ebay什么意思hcv8jop9ns9r.cn 得瑟什么意思hcv8jop8ns1r.cn 语无伦次是什么意思beikeqingting.com 结肠多发息肉是什么意思hcv8jop9ns8r.cn
什么牙膏好hcv7jop7ns0r.cn 金融行业五行属什么hcv7jop9ns9r.cn 额头凉凉的是什么原因wuhaiwuya.com 保安的职责是什么hcv9jop4ns6r.cn 同房肚子痛是什么原因hcv9jop5ns4r.cn
禅宗是什么意思hcv9jop0ns9r.cn 支原体衣原体是什么病hcv8jop2ns9r.cn 人为什么会哭hcv8jop4ns1r.cn 六月初六是什么星座hcv9jop6ns0r.cn 球镜是什么意思hcv8jop1ns9r.cn
原住民是什么意思hcv7jop6ns8r.cn 视力s和c代表什么hcv8jop9ns0r.cn 什么人容易得多囊卵巢adwl56.com 阴平阳秘是什么意思hcv8jop1ns8r.cn 侯亮平是什么级别hcv8jop1ns6r.cn
百度