西城

指尖代码,手上年华

联系 聚合 管理
  20 Posts :: 0 Stories :: 62 Comments :: 0 Trackbacks
这一阵在看CORBA,想找一个优秀的开源实现并不容易。MICO性能太差,没有考虑,omniORB还好,只是配置着有点麻烦,
Naming Service那部分用了好长时间也没让程序成功运行。orbit差不多是所有的实现里面最为高效的一个,因为它是
用C实现的,主要的绑定语言是C和perl。GNOME项目组正在用它。至少从实用性角度看,它要比omniORB好的多。
在看其中的例子时,发现了在一些问题的处理上,C的实现非常高效,而且并不复杂。相比之下,
C++则显得有点臃肿,效率低下。
第一个问题:类的实现。
C语言里没有类的概念,而IDL定义的接口则需要实现类似于对象的概念。C中的方法是将类作为方法的前缀,因为我们
最终调用的还是方法,而将类作为函数名的前缀之后,就能保证方法名字的唯一,因为类名是不同的,一个类中的函数
名也是不同的。这样就大大降低了开销,所有的一切都是通过函数调用来完成的。
比如
CORBA_ORB类中的resolve_initial_references方法,若参数是“RootPOA”
则C中的实现是
CORBA_ORB_resolve_initial_references(*orb,"RootPOA",ev);
其中第一个参数就是调用此方法(resolve_initial_references)的类,第三个参数就是我所说的第二个问题:异常处理。
C++中引入了throw...catch控制接口和exception类。优点自不待言,缺点却也不少,效率损失,程序结构的混乱。
在C的大部分函数中,我们可以看到另一种解决方法——额外的参数。
通过附加一个额外的参数来表明错误,然后检测错误,这样的开销比用throw....catch小的多,而且没有破坏程序
结构。
C虽然只是一种面向过程的语言,没有那么多的“高级特性”,但通过各种封装,在不损失语言的简洁和高效的同时,
C的实现也是有很多优点的。这也是为什么C总能稳居语言排行榜的第二位的原因。
posted on 2012-03-24 22:55 西城 阅读(1702) 评论(26)  编辑 收藏 引用 所属分类: C/C++

Feedback

# re: C和C++在两个小问题上的对比 2012-03-26 00:27 陈梓瀚(vczh)
你虽然论证了C++编译时间慢,但是这丝毫不影响运行时效率啊。而且C++封装层次高,所以你正确使用C++写一个程序,花的时间要比C少很多,就算加上慢的编译速度,也是更划算的。

举个例子“这样就大大降低了开销,所有的一切都是通过函数调用来完成的。
”。没错,这有开销,但这个开销是在编译器里面的,最终生成的运行时代码,还是跟C语言一样。一次性的东西都不用管它。  回复  更多评论
  

# re: C和C++在两个小问题上的对比 2012-03-26 10:50 墨魂
@陈梓瀚(vczh)
但从orbit与omniORB的实现来说,我觉得还是C的实现更好,因为你用orbit写分布式程序时,最终服务器端的大部分代码都直接有orbit帮你生成,你只用写你需要实现的功能这一块就好。但omniORB却全是要自己手动去写。运行时代码是和C一样,但throw...catch这样的代码一直都在程序中,不仅影响程序逻辑,在实现上也比直接传一个参数低效的多  回复  更多评论
  

# re: C和C++在两个小问题上的对比 2012-03-26 10:59 zjh
@陈梓瀚(vczh)
正确使用C++写一个程序,花的时间要比C少很多
正确使用c++比正确使用c,所花费的时间是不可等日耳语的
不敢苟同,c++太复杂了,稍不留神,就有可能出错,效率低下,只要看看c++出版了那么多书籍就知道了,至今没有一个编译器能完全实现标准c++,也说明c++过于复杂
  回复  更多评论
  

# re: C和C++在两个小问题上的对比[未登录] 2012-03-26 15:27 陈梓瀚(vczh)
你要是非要拿一个类库来说,那我也可以说我山寨过一个boost::spirit,那种优美兼高效的parser写法,C永远都做不到呢。这有什么意思。  回复  更多评论
  

# re: C和C++在两个小问题上的对比[未登录] 2012-03-26 15:29 陈梓瀚(vczh)
@zjh
学习C++是一次性的,而写C语言程序则是每一次都要做的事情。你这么比较不公平。一个更极端的例子,你花更多的时间去学习haskell,后面每一个程序的尺寸,可能是C语言的1/30,而且健壮性基本不用care因为语言保证了你很难不健壮,性能也不差。这个开发效率高不高,当然是算总的时间,岂能算一个程序的时间?  回复  更多评论
  

# re: C和C++在两个小问题上的对比 2012-03-26 15:37 墨魂
@陈梓瀚(vczh)
我是从一个类库开始说,但并不是只是这一个类库这样。比如QT和GTK相比,明显QT的效率要比GTK相比要低的多。我比较的重点只是运行的性能还有就是错误处理那一块的效率,至于你说的那些优美与高效的写法,如果与同样的C实现相比,也不一定就见得高效与优美。
  回复  更多评论
  

# re: C和C++在两个小问题上的对比[未登录] 2012-03-27 09:12 Chipset
C语法和用法相对比较简单,C++语法和用法相对复杂,或者说看你会不会用C++罢了。小程序比较快慢没有意义,上下差不了几个毫秒,可以看成误差。我们还是比个比较大的程序吧,你觉得最新的Linux系统显著比最新的Windows快吗?前者是C写的,后者是C++写的。测试了很多项,都是常用的,除了文件读写外(EXT4对NTFS,个人觉得是格式问题),其它项Linux全军覆没。在Linux一个网站上比较的Ubantu和Win7,自己谷歌一下吧,我不解释。  回复  更多评论
  

# re: C和C++在两个小问题上的对比[未登录] 2012-03-27 09:43 Chipset
http://www.phoronix.com/scan.php?page=home
这里有很多比较,有硬件的,也有软件的。
至于你文中提到的C++抛出异常,我真想知道有多大开销,问题是你抛什么异常,怎么抛异常,怎么处理异常。根据经验,异常处理会难倒很多C++老手,所以我怀疑你怎么使用异常,会不会很好的使用。
C语言稳居什么排行榜的事情跟效率有关吗?既然C那么好用为何比排名第一呢?你不觉得你那种论断荒唐吗?
至于你提到的图形库,GTK+和QT,这玩意怎么比呀。作出的图形不同的画质计算量会千差万别。都是用C写的界面,GNOME和XFCE速度相差很大,这怎么解释。即使如此,KDE也未必比Gnome慢哪里去,还在上面那个链接,你自己看。  回复  更多评论
  

# re: C和C++在两个小问题上的对比 2012-03-27 11:53 zjh
@Chipset
谁告诉你windows是用c++编写的,windows内核也是用c和汇编写的  回复  更多评论
  

# re: C和C++在两个小问题上的对比[未登录] 2012-03-27 12:43 Chipset
唉,我说楼上的那位。Win内核是用C++写的,少量Intel汇编,你去问微软的架构师好了,我不解释。。。  回复  更多评论
  

# re: C和C++在两个小问题上的对比 2012-03-27 12:53 墨魂
@Chipset
ubuntu并不能代表LINUX,它只是一个类似WINDOWS的傻瓜化的操作系统。
WINDOWS和INTEL的联盟使得WINDOWS针对x86平台进行优化,但LINUX没有这样的支持,而且linux要支持各种硬件平台,所以代码要尽量通用,可移植,当然在某些方面比不过只做x86的windows.  回复  更多评论
  

# re: C和C++在两个小问题上的对比[未登录] 2012-03-27 12:54 Chipset
@zjh
顺便给你扫盲一下吧。微软的所有产品(除了.net框架的一部分基类用了C#),其余是一色的C++程序,就连C#编译器都不例外,当然了,个别地方有点Intel汇编。
若干年前Windows Phone上尝试了一下用C#写了个软键盘程序,发现速度太慢,最终只好又退回到C++。DOS是用汇编写的,从Win95以后,都是C++代码外加少量汇编。Win2K的代码泄漏过一次,不知道现在网上是否还能下载到,是用C++写的,这个能看到。

不要觉得WinAPI是些C代码就认为Win内核是用C写的,你可以去问微软的架构师。。。  回复  更多评论
  

# re: C和C++在两个小问题上的对比 2012-03-27 12:59 墨魂
@Chipset
KDE的内存占用要比Gnome大很多,这是我自己测得的结果。如果KDE真如你说的那么好,各大发行版为什么都默认的是GNOME而不是KDE,连SUSE在12.1都是。C不是第一,只是因为相对于JAVA来说,C还是太难。愿意学下去的太少。不过3月分的语言排行榜你应该看过,JAVA--17.110%,比上月下滑2.60%,C占
17.087%,上涨1.82%,这总不会是无缘无故的。C++8.074%,下滑0.71%,并不说C++不好,只是有太多自以为是的C++程序员了。  回复  更多评论
  

# re: C和C++在两个小问题上的对比[未登录] 2012-03-27 13:31 Chipset
@墨魂
唉,那个排名能说明个啥呀,跟效率没关系是不是?
其实C++和C速度上没差别,你可以看下struct和class的内存布局,内存布局都一样,哪来的速度差别呀。。。
C++唯一慢的地方是虚函数(C没有),需要查虚表,就一两条指令的开销带来的好处是不言而喻的。。。
至于Gnome和KDE,画面质量不同,内存和计算量相差那么大,比速度和内存有意思吗?你咋不拿控制台给Metro比速度和内存呀。。。
C++是有很多缺点被很多人指责,编译慢,语法太复杂,新手很容易写出烂代码。。。这都是真的,但是不恰恰说明很多人在用C++吗?否则怎么可能发现这么多问题呢。。。就如同我们天天骂windows一样,你见过几个人骂Linux?没有几个人用,哪里能发现那么多问题。。。  回复  更多评论
  

# re: C和C++在两个小问题上的对比[未登录] 2012-03-27 13:35 Chipset
@墨魂
如果你还要比,我还能给你举出更多例子说明C++比C快,耗费内存也少,如果有人说C++比C快耗费内存少,我同样也能举出很多反面的例子。。。  回复  更多评论
  

# re: C和C++在两个小问题上的对比 2012-03-27 15:13 zjh
@Chipset
你是不是想说微软的C编译器和链接器也是c++写的?,操作系统内核从来也没有用c++写过,注意是内核,不是操作系统,windows是微内核。
不巧,我还真有win2k的源代码,要不要贴上来让你看看? 先给自己扫盲吧  回复  更多评论
  

# re: C和C++在两个小问题上的对比[未登录] 2012-03-27 16:13 Chipset
@zjh
建议你谷歌一下吧,或问微软的架构师,感觉这玩意没啥好争论的。  回复  更多评论
  

# re: C和C++在两个小问题上的对比[未登录] 2012-03-27 16:31 Chipset
就说NT吧,不是微(micro)内核,也不是单(monolithic)内核,应该算Hybrid。你可以搜索到NT架构,我也不清楚你说哪一部分。HAL层我估计应该用汇编,据说这些汇编主要来自一个祖籍台湾人的贡献(你可以了解一下微软的历史,那几个技术鼻祖)。再上面一层(Kernel mode drivers 和 micro kernel),古老的代码应该是C写的,后来改写的代码是C++的,再上面也是这样,古老的代码是C的,后来的是C++的。其实不仅Windows,Office也是这样的,最古老的代码是汇编,后来的用C,C++出现以后所有的新东西都用C++来写。你不是有win2k代码吗,你最好找到我说的那一层看看是不是这样。  回复  更多评论
  

# re: C和C++在两个小问题上的对比 2012-03-27 16:48 Chipset
@zjh
这里有个简要的图和介绍,我不明白你指代那一部分:
http://en.wikipedia.org/wiki/Architecture_of_Windows_NT

用C++写操作系统内核不是新闻,用Java写的都有。。。

这里有用什么语言编写的介绍:
http://www.lextrait.com/vincent/implementations.html
这里也可以查到:
http://www2.research.att.com/~bs/applications.html
  回复  更多评论
  

# re: C和C++在两个小问题上的对比 2012-03-27 17:48 墨魂
@Chipset
GNOME和KDE的差别有多大,你如果真的拿命令行和win8的那个什么界面比。我也没什么可说的。GNOME3.2和KDE4.7是差不多同时的产品,你自己可以去看他们之间究竟是不是有你所说的那么大的差别。

你之前说排名没用,现在又来说C++有那么多人用,那这又有什么用?我觉得排名里C++不断下滑是有原因的,你若觉得没什么问题也罢。  回复  更多评论
  

# re: C和C++在两个小问题上的对比 2012-03-27 19:19 zjh
@Chipset
你说什么就是什么吧,反正我手里的win2k源代码不是c++的,难道是盗版?
java写操作系统,是毕业设计么? 也许等到芯片的计算能力大大提高后,可以吧java虚拟机固化到芯片,就可以用java写操作系统
摘录一段代码
VOID
KiInitSystem (
VOID
)

/*++

Routine Description:

This function initializes architecture independent kernel structures.

Arguments:

None.

Return Value:

None.

--*/

{

ULONG Index;

//
// Initialize dispatcher ready queue listheads.
//

for (Index = 0; Index < MAXIMUM_PRIORITY; Index += 1) {
InitializeListHead(&KiDispatcherReadyListHead[Index]);
}

//
// Initialize bug check callback listhead and spinlock.
//

InitializeListHead(&KeBugCheckCallbackListHead);
KeInitializeSpinLock(&KeBugCheckCallbackLock);

//
// Initialize the timer expiration DPC object.
//

KeInitializeDpc(&KiTimerExpireDpc,
(PKDEFERRED_ROUTINE)KiTimerExpiration, NIL);

//
// Initialize the profile listhead and profile locks
//

KeInitializeSpinLock(&KiProfileLock);
InitializeListHead(&KiProfileListHead);

//
// Initialize the active profile source listhead.
//

InitializeListHead(&KiProfileSourceListHead);

//
// Initialize the timer table, the timer completion listhead, and the
// timer completion DPC.
//

for (Index = 0; Index < TIMER_TABLE_SIZE; Index += 1) {
InitializeListHead(&KiTimerTableListHead[Index]);
}

//
// Initialize the swap event, the process inswap listhead, the
// process outswap listhead, the kernel stack inswap listhead,
// the wait in listhead, and the wait out listhead.
//

KeInitializeEvent(&KiSwapEvent,
SynchronizationEvent,
FALSE);

InitializeListHead(&KiProcessInSwapListHead);
InitializeListHead(&KiProcessOutSwapListHead);
InitializeListHead(&KiStackInSwapListHead);
InitializeListHead(&KiWaitInListHead);
InitializeListHead(&KiWaitOutListHead);

//
// Initialize the system service descriptor table.
//

KeServiceDescriptorTable[0].Base = &KiServiceTable[0];
KeServiceDescriptorTable[0].Count = NULL;
KeServiceDescriptorTable[0].Limit = KiServiceLimit;
#if defined(_IA64_)

//
// The global pointer associated with the table base is
// placed just before the service table.
//

KeServiceDescriptorTable[0].TableBaseGpOffset =
(LONG)(*(KiServiceTable-1) - (ULONG_PTR)KiServiceTable);
#endif
KeServiceDescriptorTable[0].Number = &KiArgumentTable[0];
for (Index = 1; Index < NUMBER_SERVICE_TABLES; Index += 1) {
KeServiceDescriptorTable[Index].Limit = 0;
}

//
// Copy the system service descriptor table to the shadow table
// which is used to record the Win32 system services.
//

RtlCopyMemory(KeServiceDescriptorTableShadow,
KeServiceDescriptorTable,
sizeof(KeServiceDescriptorTable));

//
// Initialize call performance data structures.
//

#if defined(_COLLECT_FLUSH_SINGLE_CALLDATA_)

ExInitializeCallData(&KiFlushSingleCallData);

#endif

#if defined(_COLLECT_SET_EVENT_CALLDATA_)

ExInitializeCallData(&KiSetEventCallData);

#endif

#if defined(_COLLECT_WAIT_SINGLE_CALLDATA_)

ExInitializeCallData(&KiWaitSingleCallData);

#endif

return;
}
  回复  更多评论
  

# re: C和C++在两个小问题上的对比[未登录] 2012-03-28 09:20 Chipset
@zjh
Java写系统还真有,也不是什么毕业设计。你可以谷歌下JNode,除了一点汇编,其它全是用Java写的。
至于你说把虚拟机固化到芯片里,虽然我没见哪家这么干,但是我确实听说有的ARM芯片可以直接执行字节码。

我们做嵌入式,芯片的计算能力非常有限,内存也跟台式机没得比,是很在乎资源消耗的。以前一直认为C++比C慢很多,耗费资源也多,关于C和C++之间的速度差别查阅了很多资料,评测过N次,发现几乎没啥差别。

C++的缺点是很明显的,新手很容易写出垃圾代码,速度慢耗费内存多,但优点也很明显。我们目前做的一个程序大约2百万行源代码,C++代码大约90%以上,C代码大约5%,还有1%不到的Lua。如果C++的部分也用C来做,你想想源代码量会有多大,维护起来会有多痛苦...  回复  更多评论
  

# re: C和C++在两个小问题上的对比[未登录] 2012-03-28 09:33 Chipset
@墨魂
Gnome和Xfce都用C,但是速度差别那么大怎么解释?很多事情跟语言关系不大对不对。再举个例子,Chrome,FireFox,IE都用C++来写,速度和资源消耗是不是也差别很大?这又怎么解释?
我再举个例子吧,MTL听说过吧,做计算的。做数值计算,C和C++没法跟Fortran比速度,同样的算法,速度得差20%,但是MTL开发出来后,尤其4.0以后把Fortran都秒飞了,你能说C++不行?那为啥不用C来做,如果C真的那么快?

任何语言都有优点和缺点,否则某种语言早就一统江湖了。。。  回复  更多评论
  

# re: C和C++在两个小问题上的对比 2012-03-28 11:17 墨魂
@Chipset
我没有说过C就一定比C++好,问题都是在库的设计上,C++的库设计的不好会有性能损耗,设计的好的话跟C比也会很多优势。

MTL是很好,但没有用C来做 就不是说用C不行。只是刚好这个库用C++来写了而已。  回复  更多评论
  

# re: C和C++在两个小问题上的对比[未登录] 2012-03-28 16:04 Chipset
@墨魂
Gnome和KDE都是应用,Linus Torvalds也在公开场合说过KDE做的很不错,否则在那个C的世界KDE早死了。

Qt的版本升级很快,看来很多人在用(如果没几个人用那还有必要频繁升级吗?)再想想Qt商业应用得花钱买版权,如果Qt跟GTK+比真的那么差,谁愿意花钱买不好的东西呢?用免费的GTK+(C)或gtkmm(给C++用)岂不更好?

顺便说下zjh贴的那段代码,我真看不出是C的。C89和C94没有//的注释符号,C99的规定是何年月啦,微软的编译器哪里能升级那么快?Win2K能赶得上吗?  回复  更多评论
  

# re: C和C++在两个小问题上的对比 2012-03-28 16:33 墨魂
@Chipset
QT主要是功能较为丰富,而GTK+主要是做界面。再者KDE出来的比较早,GNOME只是不满于KDE的设计而成立的。所以单论界面来说,GNOME并不比KDE差,再者KDE设计的太过复杂,并不符合一般用户的使用习惯,所以GNOME会后来居上。  回复  更多评论
  


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理