分享
 
 
 

再谈Delphi vs VC++

王朝delphi·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

偶然来找一个文件,却发现这里关于VC++和Delphi的讨论很是激烈。看了大家写的一些

文章,觉得有些看法正确,有些就很偏颇甚至错误(也许无知?很抱歉我这样说:-)。我

无意与任何人争论,更愿意把这看成是技术上的讨论。应该本着公正,不带偏见的态度

(这并不意味着非要平分秋色,一切应以事实为准)。我用过除TP1以外的所有版本的

Turbo Pascal,所有版本的Turbo C/Borland C++,所有版本的Delphi和C++ Builder;

以及MSC 5.0/6.0,MSC/C++ 7.0和Visual C++ 4.2/5.0。不敢说有多高的水平,至少也

算有一点经验吧。下面就谈一下我的看法。

1. 编译器

应该说Borland的编译器是最好的。因为Borland有全世界最好的编译器开发组(虽然

Anders Hejlsberg离开了)。从技术上来讲,Borland领先任何竞争对手至少2~3年。一

般来说,Borland的编译器总是能生成更小的代码并且通常(并不是在任何情况下)更快

的代码。

紫云英、曾登高在文章中说VC++编译的程序小,这其实是使用了动态连接的结果。M$把

VC++的运行库(msvcrt*.dll, msvcp*.dll, mfc*.dll, 你看看这些文件加在一起有多大)

在安装Windows时就放在了System/System32目录中了。两位说“协商接口”的问题,恐

怕是对某些英文文章的理解错误。M$就是不愿意在Windows中带上其他公司的运行文件,

没有技术上的原因。

其实Delphi/C++ Builder不论在动态连接或静态连接的情况下,生成的程序都要比

VC++的小。比如MDI的例子程序:在Delphi/C++ Builder中选New ... | projects |

MDI Application,在VC++中用MDI App Wizard;生成的程序功能是非常类似的。

下面是比较结果:

(Delphi打开优化,C++ Builder使用最大速度优化,VC++ 5使用最小代码优化)

Delphi 3 Delphi 5 C++ Builder 5 VC++ 5

Dynamic Link 21k 35k 44k 70k

Static Link 253k 398k 467k 490k

凡是使用了应用类库的程序(不管是MFC,OWL,VCL以及新的CLx框架)都要比不使用的大

不少。这是因为目前的智能连接(Smart Link)技术还只能针对全局变量/过程,而不能

用于对象结构。哪怕你只使用了某个类(或被这个类间接引用)的一个属性或方法,这个

类以及它所引用的所有类都全部被连接到EXE中。目前所有的编译器都没有解决这个问

题。

(PS: 其实能生成最小代码(真编译)的高级语言编译器是Turbo Pascal,不信你写程序

比较一下:

program Test;

begin

writeln('Hello, world.');

end.

生成的EXE不到1.5K。而同样的C程序:

#include <stdio.h>

main()

{

printf("Hello, world.\n");

}

最精悍的C/C++编译器生成的代码也有6K。

)

那么几个编译器生成的代码质量又如何呢?

举一个例子,比如我们在编程时经常用到的for循环语句:

(1) Object Pascal:

procedure Foo;

var

i, j: integer;

begin

for i := 0 to 15 do j := j + i;

end;

(2) C++

void Foo(void)

{

int i, j;

for (i = 0; i < 16; i++) j = j + i;

}

Delphi 3生成的代码(打开优化): 字节数 时钟周期

00424AA9 33C0 xor eax,eax 1

00424AAB 40 inc eax 1

00424AAC 83F810 cmp eax,0x10 1

00424AAF 75FA jnz -0x06 0 (可并行)

-----------------

8 3

C++ Builder 5生成的代码(最大速度优化):

00401535 33C0 xor eax,eax 1

00401537 40 inc eax 1

00401538 83F810 cmp eax,0x10 1

0040153b 7CFA jl -0x06 0 (可并行)

-----------------

8 3

Visual C++ 5生成的代码(最大速度优化):

27: for (i = 0; i < 16; i ++)

00401205 mov ecx,dowrd ptr [j] 1

00401208 xor eax,eax 0 (可并行)

28: {

29: j = j + i;

0040120A add ecx,eax 1

0040120C inc eax 1

0040120D cmp eax,10h 1

00401210 jl Foo(0x0040120a)+0Ah 0 (可并行)

00401212 mov dword ptr [j],ecx 0/1 (取决于上一条指令的分支预测情况)

30: };

-----------------

16 4.2 (假定分支预测准确度80%)

VC++ 5的最小代码优化生成也有11个字节:

27: for (i = 0; i < 16; i ++)

00401205 xor eax,eax 1

28: {

29: j = j + i;

00401207 add dword ptr [j],eax 1

0040120A inc eax 1

0040120B cmp eax,10h 1

0040121E jl Foo(0x00401207)+7 0 (可并行)

30: };

-----------------

11 4

注:

(1) Delphi/C++ Builder的结果是用Turbo Debugger直接反汇编的,VC++ 5的结果是从

集成环境的源级调试得到的。

(2) 时钟周期数以Pentium处理器为例,实际上,对于没有并行执行单元的CPU(比如

386/486和Nx586等)VC++ 5生成的代码速度还要更慢一些。

(3) 分支预测准确度源自Intel的"Pentium Optimization Reference"。不过与具体程

序密切相关,一般来说程序中的条件转移指令越密集则分支预测准确度越低。

可以看出,Delphi/C++ Builder的这段程序有1~1.2个时钟周期的优势。这主要是因为

Delphi/C++ Builder的编译器比较智能,根本不编译无用的废语句。

(有趣的是,对于这段程序而言,VC++ 5的最大速度优化反而不如最小代码优化生成的

代码运行速度快。)

不要以为1~1.2个时钟周期不算什么,整个程序的快与慢就是这样一个个时钟周期积累

出来的。而且就这几条指令而言相当于快25%~28.6%,是非常可观的数字。

我没有用VC++ 6测试(我从VC++ 5以后不再使用VC了,因为C++ Builder 5能完全兼容

VC --- 这种兼容性从C++ Builder 3开始就有了,不过一开始并不完善),不知道是否

有改进。有人有兴趣的话请测试一下。

有兴趣的话,可以去Jake's Code Efficiency Challenge(http://www.xnet.com/~johnjac)

看一看。那有代码运行性能挑战。目前Delphi/C++ Builder在6项测试中保持5项领先。

(PS:Delphi 2就曾在1996年的PC Week的性能测试中击败过VC++ 4.2)

2. 语言特性

首先我不想评价所谓“Pascal是玩具语言”这种无知的说法。某些连Basic都用不好的

人是不可能正确评价其它语言的优劣的。至于“只配高中生使用”就更加可笑了:

Peter Norton没上过大学,id software的John Carmack没上过大学,你不服气?!

请不要嘲笑高中生,大多数程序员可能永远也达不到这些“高中生”的水平。创造性工

作需要的是天才,你认为天才相当于什么学位?:-)

(1) 预处理,宏以及.H文件

Object Pascal不支持预处理,其实是不需要。无法直接编译源代码的编译器才需要预

处理器的支持(用于翻译/规范源程序(也包括.H之类)以利于编译)。预处理器的出现是

因为当初Ken Thompson和Dennis Ritchie要在只有256K内存的PDP-11上实现C编译器难

度很大,才采取的折衷办法。现代大多数C/C++产品已经把预处理器包含在编译器中了。

(PS:C中采用尽可能短的关键字/运算符也是由于这个历史原因)

至于macro和.H则应该说是垃圾特性,只是由于兼容性的考虑才保留下来的。ANSI/ISO

C/C++规范中明确建议:“不要使用macro和.H,应该使用程序中的常量定义和函数替

代”。因为macro和.H不是C/C++的语言特性(这是真的!),没有明确统一的语法定义。

还会导致编译速度降低,另外由于macro在每个使用的地方被展开(不是调用),大量使

用macro会使生成的代码臃肿。

(2) 集合,子界类型

C++不支持这些Object Pascal的原生类型(编译器能直接识别的)。但可以用类来模拟,

毕竟C++的对象结构是最复杂灵活的(Ada除外)。不过性能有损失。

(3) 枚举类型

Object Pascal不支持为每个枚举元素指定值。

例如C/C++中可以定义:enum AWeek {Sun = 1, Mon, Tue ...};

Object Pascal中只能定义:AWeek = (Sun, Mon, Tue ...);

(4) 数组

C/C++不支持Object Pascal中指定下标的数组,下标只能从0开始。

(5) 结构

Object Pascal不支持struct(在Pascal中称为record)中的位域(bitfield)。bitfield

可以bit为单位(不需要整字节)来存储结构成员,可以减小结构的存储空间。不过存取

效率会有所降低。

(6) 字符串

字符串处理是Object Pascal的强项之一。能够支持灵活高效的串处理。严格意义上讲,

C/C++不能算支持原生的字符串类型。char *和char[]更近似于用户自定义类型,因为

编译器不支持字符串的内存自动分配和回收,需要用户自己调用malloc()和free()。

Object Pascal也支持C/C++风格的字符串(称为PChar)。不过string类型更加强大。从

实现上来看,Object Pascal的string类型使用前缀表示串长度(1字节前缀的short

string和4字节前缀的long string,两种string自动兼容,并且long string也兼容

PChar),C/C++中的char *和char[]使用后缀chr(0)表示串结束。不同的表示方法对串

处理性能有很大的影响:对于大量,复杂的字符串操作,用Object Pascal可以写出比

C/C++快几十倍的程序(许多用Pascal写的Pascal编译器,比如Free Pascal,

Pascal Pro等,虽然技术水平一般,但编译速度也很快,在某种程度上也得益于Pascal

的字符串处理效率)。比如取串长度函数Length/StrLen(),Object Pascal的实现只需

要一条mov指令,而C/C++的实现则需要进行重复串扫描直到找到结尾0为止。

Object Pascal的string类型在支持unicode字符方面也有优势。要知道C/C++的字符串

给现代操作系统支持unicode字符带来了很大的困扰,比如串'ABC'的unicode表示为:

41 00 42 00 43 00,这使C/C++程序根本无法处理这种字符串。虽然修改编译器可以很

容易解决这个问题,但光修改编译器是不够的,还要修改操作系统,否则以前的大量

C/C++程序根本无法在新操作系统上使用(这简直是灾难 --- 你连Notepad都没了,怎么

办?:-)。Windows采用凡是涉及字符串处理的API都提供两套的解决方案。比如TextOut,

有用于处理ASCII字符的TextOutA和用于处理unicode字符的TextOutW。而Unix/Linux采

用另一种办法:凡是涉及字符串处理的API都使用UTF8压缩编码(一种类似于RTF的编码

方法:凡是ASCII字符都直接存储,多字节字符则用\进行转义),虽然(勉强)保证了兼

容性却也代价不小。

(PS:C++中的String/AnsiString是用类模拟的,所以性能...)

(7) 多重继承

毫无疑问,Object Pascal不支持多重继承;并且也看不出Borland有增加这一特性的意

向(其实增加是轻而易举的)。Object pascal通过接口(interface)实现多重继承。

interface不仅可以引入用Object Pascal实现的对象,也可以引入其他语言实现的

COM/DCOM/CORBA对象。你真的需要多重继承吗?我想大多数程序员和我一样都从来没有

使用过多重继承(连VCL这么强大灵活的体系结构都根本没有用到多重继承)。

(PS:Java和Delphi一样不支持多重继承,也使用interface来实现多重继承。其实这并

不奇怪:JDK 1.2和Java 2主要是由Borland开发的,Sun只挂名而已。不信你看Java类

库是不是和VCL很象。:-)

(8) 对象模板

Object Pascal不支持对象模板。因为对象模板不过是宏的语言实现而已(宏本身不是

C/C++的语言特性)。

(9) 重载

Object Pascal支持函数/过程的重载,不支持运算符重载。C++全部支持。

(PS:我个人倾向于Object Pascal应该增加对运算符重载的支持)

(10) 位及逻辑操作

Object Pascal和C/C++在这方面没什么差别。

C/C++的&,|,~,^,>>,<<,&&,||,!等效于Object Pascal的and,or,not,xor,

shr,shl(and,or,not,xor既用于位操作也用于逻辑操作)。不过C/C++不支持逻辑

xor(A xor B = A and not B or not A and B,还是可以实现的)。

(11) 风格

其实这是我更倾向于使用Delphi的一个重要原因(由于工作的原因,我也经常使用C++和

汇编)。就象有些文章所说的:“Object Pascal和C++是同一重量级的语言”,确实难

分轩轾,差别反而主要是在风格上。C++强调灵活,而Object Pascal更注重整洁和优美。

《程序设计语言:设计与实现》一书的作者也称赞Pascal是“一种极优美的语言”。有

人因此认为Pascal“笨拙”。其实应该是“大道至简”。我认为即使用C++写程序也还

是工工整整的好,不要卖弄技巧。只有水平不高不低的程序员才喜欢卖弄技巧(水平太

低的卖弄不了,太高的又不愿卖弄了)。就象有人评李昌镐的棋“平淡”,但马晓春再

怎么“鬼才”也只能甘拜下风。

上面说的其实都是C++ vs Object pascal。不过也适用于VC++ vs Delphi。

(PS:VC++其实并未实现全部ANSI/ISO C++ 95规范(目前的最新标准)的特性(所以有人

戏称之为C+)。而C++ Builder则完全兼容ANSI/ISO C++ 95规范,并支持AT&T(C的诞生

地)和Unix V的全部C++扩展特性。有人称“M$坚持工业标准,Borland随意修改”,这

是不对的。Delphi也全兼容ANSI/ISO Pascal 1983/92规范,以及Apple Object Pascal

(用过Code Warrior Professional的应该知道Apple的Object Pascal)。

)

3. 功能及其他

(1) 易用性

毫无疑问Delphi有巨大优势,这不用多说了吧。

(PS:Delphi的真正伟大之处在于并不因为易用而降低技术水准。你需要复杂性就有复

杂性,你需要灵活性就有灵活性;不用可视化也一样写程序(可视化只是Object Pascal

对象结构的另一面),不用VCL也一样写程序)

(2) 适用范围

VC++几乎能做任何硬件允许的工作。Delphi也能。

(“不!!!”,我知道你会这样说,你会举出VxD。:-)

Delphi不能写VxD(其实如果你用Delphi生成OBJ,再用M$的Link连接,是可以的)是有原

因的(你见过非M$的工具能生成VxD的吗?Watcom?Symantec?GNU?...),但不是技术

上的原因。VxD的LE(Linear Executable)文件格式最早出现在Windows 3.0中,格式很

简单(比NE和PE格式都要简单),基本上是内存映象文件。但M$不知道出于什么动机就是

不允许其他公司的软件生成它的这种(专利)格式。

Delphi是可以写Windows NT的SYS和新的WDM(Windows Driver Model)驱动程序的,这些

使用普通的DLL格式。

(PS:从法律角度讲,你自己写一个程序,未经M$允许生成MS Word文件也是不行的)

(PS:玩过“奇迹时代”(Age of Wonders,http://www.epicgames.com)吗?是用

Delphi 3写的。画面和速度都优于M$的“帝国时代”。不过我不喜欢玩策略类游戏,我

喜欢的是Duke3d和Quake系列,还有Tomb Raider系列。:-)

(3) 集成开发环境

Delphi的IDE更简洁/好用一些。

(4) 数据库支持

在这方面除了Delphi的兄弟C++ Builder/JBuilder恐怕只有Power Builder能(勉强)与

Delphi相比。不过PB的性能和使用范围就差得太远了(要不怎么叫Poor Builder呢?:-)。

(PS:我的印象是现在大多数基于网络/大型数据库的C/S和多层结构的应用都是用

Delphi/JBuilder开发的)

(5) 网络功能

Delphi也有一定的优势。尤其是在Internet开发方面。

(6) 组件支持

Delphi除了基于Object Pascal的VCL/CLx外,也支持基于COM/DCOM的组件(比如ActiveX),

另加CORBA支持。VC++只支持支持基于COM/DCOM的组件。

(7) 应用框架/设计思想

VCL比MFC至少领先一代,这也毋须多言。MFC充其量不过是对OWL的(一种不太成功的)模

仿而已,从设计思想上看甚至还不如OWL。作为一种语言的基本类库(不论可视与否),

应该从大处着眼,力求简洁有效,保持一定的弹性和抽象度(抽象意味着从功能出发,

比如VCL中的TCanvas就是对Windows中DC(Device Context)的一种极好的抽象,比起MFC

中的设计高明了何止一点半点)。而不是面面俱到,一一照搬APIs(不幸的是,M$的程序

员多年以来一直在不辞劳苦地做这项工作)。看看MFC的某些类,简直惨不忍睹:通常除

了省了HWND和DC之类的参数(已经作为类的私有数据保存了),其方法(Method)简直就是

Windows API的翻版。这样做有什么意义呢?Windows API不就摆在那里吗?比如说,使

用MFC中的线程类还不如直接调用CreateThread/ExitThread/ResumeThread/

SetThreadPriority之类的API更方便快速呢。

(PS:用过DelphiX(http://www.yks.ne.jp/~hori/)吗?DirectX这么繁杂的结构可以用

Object Pascal封装得如此之好再次证明了VCL体系结构的强大)

(8) 调试

两者相差无几。VC++的源级调试更用户友好一些,而Delphi/C++ Builder对多线程程序

的调试支持更好。

(PS:要比单独的调试工具,Borland的Turbo Debugger可就要比M$的CodeView强多了)

(9) 运行环境/系统需求

应该说差不多。VC++的启动速度确实要快于Delphi(这主要是相对于Delphi 4+而言,

Delphi 3的启动还是很快的)。这很大程度上是由于一个事实:VC++主要是一个基于文

本编辑器的传统开发环境。Code Warrior Professional不是启动更快吗?

至于“一个数据库程序要带上3~5MB的BDE运行文件”的说法,这可能是由于在安装制作

工具(InstallSheild,Wise之类)中使用了“全部BDE安装”(默认)而不是“部分BDE安

装”。如果你只使用Access,dBase,FoxPro,Paradox之类的桌面数据库,只需要几百

K的运行文件就可以了。用M$的工具开发的数据库程序也要带上一大堆ODBC,DAO,Jet,

ADO,MSDE之类的运行文件。在Delphi 5中,如果使用ADOExpress,InterBase Express

访问数据库的话,可以不带BDE。

(PS:不管怎么说,Borland在Delphi/C++ Builder的启动速度方面还是要努力改进!)

(10) 产品质量/稳定性

有文章称“VC++的质量好,稳定性高”。真的是这样吗?Visual Studio的Service Pack

不是都出到4了吗?什么是Service Pack?主要不就是Bug Fix + Patch吗?!Borland

的工具也并不完美,Delphi 3的VCL中确实存在“内存漏洞”,会导致用D3开发的程序

有时(并不总是)退出后不能释放分配的内存。VC++的问题也不少:IE是用VC++写的吧,

上网时多启动几个,开开关关,最后全关闭,看看你的系统资源剩下多少了?还经常导

致“General Protection Error”。Ultra Edit是用VC++写的吧,也有同样的问题。其

实说到底,程序质量好不好,运行稳定不稳定,主要取决于开发者的水平/责任心。比

如说Tomb Raider系列和Quake系列游戏同是用VC++开发的,但画面质量和运行速度显然

Quake系列更胜一筹。象美国航空航天局(NASA),俄罗斯宇航局(RSA),美洲银行(Bank

of America,资产超过5000亿美元的大银行),其他诸如American Airlines,AT&T,

BMW,Compaq,BBC Television,British Telecom等大型机构/公司都在用Delphi开发

复杂的,企业级(可笑的是,有人居然称“用VC开发企业级的桌面应用”,殊不知企业

级应用和桌面应用是相对而言的)的应用系统(在http://community.borland.com

(Borland社团站点)上有关于用Delphi和C++ Builder开发的产品介绍),如果有人还要

说“...稳定和可靠是硬道理,只好忍痛割爱了”,那他恐怕只好自制开发工具

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有