020-29133788
    资 讯
    您的位置:首页 >> 资 讯 >> 软件应用 >> 编程开发 >> 正文
    ]C++标准与实作之间

    点击:   发布日期:2013-01-25

    本文来自 www.020fix.com


    对一个开发环境而言,最重要的是增加生产效率和降低生产成本,对标准语法的支援反而没那么重要。不过若是对语法标准充分支援,可以省下许多时间去处理奇奇怪怪的bug。

    文章有点旧,BC核心已经到了5.5,GCC已经推出了全新编译引擎的4.0版,VC也迈入了manage code的新层次。这些编译器都已经不可同日而语。(我想新的BC和GCC更能充分支援C++标准,而VC离标准说不定更远,微软有微软的想法)。反过来说,拿古老的Turbo C++来作这些测试,应该会惨不忍睹吧

    *******************************************************************
    C++ Primer 答客问 (27) 【标准与实作之间】

    PC 环境上三种编译器对 C++ Standard 的支援

    侯捷  jjhou@ccca.nctu.edu.tw
    1999.12.29 第一次发表于
    清大.枫桥驿站(140.114.87.5).电脑书讯版(Computer/CompBook)

    本文将于日后整理于 侯捷网站/答客问 /C++ Primer 中文版
    侯捷网站:www.jjhou.com
    ----------------------------------------------------------------

    ●C++ Standard 相容编译器

    我想很多人关心,目前市面上哪些厂牌的 C++ 编译器,完全支援 C++ Standard。C/C++ User Journal, Nov. 1999 的【C/C++ Stanadrd FAQ】专栏中,P.J. Plauger 对此问题的回答是:目前还没有完全支援 C++ Standard 的编译器产品。P.J. Plauger 阅历广泛,他的文章提到不同平台上的多种C++ 编译器(但并没有深入谈论,都只浅浅带过)。

    回忆历史,C Standard 定案后,市面上立刻出现一大堆宣称与标准规格完全相容 的 C 编译器。为什么符合 C++ 标准规格的编译器却是如此难产呢?我想因素之一是,C++ 远比 C 复杂得多,后期导入的一些性质(如 member templates, template partial specialization...)在编译器技术层面上更是高难度。因素之二是,C++ Standard library 是个浩大的工程,而编译器通常是以 bundle 的方式搭配其他公司的 C++ Standard Library,所以彼此的进度、技术、相容性都需要更多时间来协调配合。因素之三是,C++ 编译器的价值比较,已经不再只是单纯地比谁对 C++ Standard 的支援程度高(或甚至也不是比较谁的编译速度快),而是比较在特定平台上对客户是否有更多的企业服务。拿 Windows 环境上的 C++ 编译器来说,「谁提供更好的 Windows 应用软体开发工具与开发资源」可能比「谁更贴近 C++ Standard」,对客户而言更为重要。

    但是大家还是会很关心哪家编译器最贴近 C++ Standard -- 即使这不影响你对 C++ 编译器的选择。

    ●个人经验

    自从我将 L&L(Lippman & Lajoie)的《C++ Primer》译出后,面对 C++ Standard 所规范的许多崭新性质,就有一股跃跃欲试的冲动。其后由于个人兴趣,也因为课程需要,把《C++ Primer 中文版》整个重新检阅一遍,并动手在三种不同的编译器上进行测试(都是 PC/Windows 平台)。以下整理我的个人经验,供各位参考。

    我尽量为每一个主题列出一份简短而完整的测试码。这些或许不是太严谨的测试,但是如果这些符合 C++ Standard 的程式码无法通过编译,我们说这个编译器未能奉行 C++ Standard,并不过份。但反过来说,通过我所列之简易测试者,或许仍有可能在更复杂的情况中出错(尤其是template 相关主题)。如果您有相关经验,欢迎提供出来造福大家。

    没有什么好点子,可以对以下各个主题编号排序。所以我以它们出现在《C++ Primer 中文版》上的页次为序。拥有英文版的读者请注意,中文版和英文版页次完全相同。


    ●测试环境

    我的测试环境是:Intel Pentium,Windows 98,三套 C++ 编译器:
    (1) Microsoft Visual C++ 6.0(以下以 VC6 代表)
    (2) Inprise Borland C++Builder 4.0  (以下以 BCB4 代表)
    (3) GNU C++ egcs-2.91.57(以下以 G++ 代表)

    请注意,GNU C++ 有着各种作业平台上的各种版本。我只用手上的egcs-2.91.57(for win32) 来测试。

    我在 Windows 98 文字模式(console mode)底下进行编译。以下是三种编译器的环境设定(其中路径可能与你不同。如欲循此方式设定,请自行修改):

    ★VC6 环境设定
    @echo off
    rem
    set PATH=C:\MSDEV\VC98\BIN;C:\MSDEV\COMMON\MSDEV98\BIN
    set INCLUDE=C:\MSDEV\VC98\INCLUDE
    set LIB=C:\MSDEV\VC98\LIB

    ★BCB4 环境设定
    @echo off
    rem
    set PATH=C:\inprise\CBuilder4\BIN
    set INCLUDE=C:\inprise\CBuilder4\INCLUDE
    set LIB=C:\inprise\CBuilder4\LIB

    ★G++ egcs-2.91.57 环境设定
    @echo off
    rem
    set PATH=c:\CYGNUS\CYGWIN~1\H-I586~1\BIN
    set INCLUDE=
    set LIB=
    cls

    我的编译选项(compile options)极其简单,

    ★VC6  : cl -GX test.cpp
    ★BCB4 : bcc32 test.cpp
    ★G++  : g++ -o test.exe test.cpp


    ●发表

    我把这份内容放在 BBS/News 上,欢迎传布,无需特别知会。

    欢迎以下的讨论与指正:

    1. 如果加上任何编译选项(compile options)即可解决(避免)所列之任何一个错误的话,欢迎(敬请)告知。
    2. 如果我的文字或程式码有任何问题,欢迎(敬请)告知。
    3. 如果您有其他(未列于本文)的编译器问题,欢迎(敬请)告知。

    欢迎于 BBS/News 上讨论。如能同时转寄一份给我,以免除我遗漏观看的可能,最是感谢。如不欲公开讨论,亦欢迎将意见直接 email 给我。如欲讨论,请写实例,不要只是臆测。

    我会注明对本文有助之朋友的大名及其意见,以示感谢。


    ■C++ Primer p213 下, p.393 下
    主题:for loop 的 init-statement 区域内,所有 objects 皆为 local。
    测试结果:VC6[x]  BCB4[o]  G++[o]
    实例:

    #001 void main()
    #002 {
    #003 for (int ival=0; ival< 10; ++ival);
    #004 for (int ival=0; ival< 10; ++ival);
    #005 }

    注意:C/C++ User Journal, Oct.1999, p.94 曾提过在 VC 上的一个简易
    闪避办法,这并且也是明载于 MSDN News(Vol7, Num6, Dr. GUI column)
    上的作法。设计一个巨集如下即可解决:

    #define for   if(0); else for

    该文并说,在简单情况下可以有效运作,但并未测试太过复杂的情况。


    ■C++ Primer p262 中
    主题:STL list 建构时,直接给 list 的大小及初值(做为所有元素的相同初值)
    测试结果:VC6[o]  BCB4[x]  G++[o]
    实例:

    #001 #include <list>
    #002 ...
    #003 const int list_size = 64;
    #004 list<int> ilist1(list_size);      // BCB4 error.  VC6 ok. G++ ok
    #005 list<string> ilist2(list_size);   // BCB4 ok.     VC6 ok. G++ ok
    #006 list<int> ilist3(list_size, -1);  // BCB4 ok.     VC6 ok. G++ ok
    #007 list<int> ilist4(list_size, 0);   // BCB4 error   VC6 ok. G++ ok
    #008 list<int> ilist5(list_size, 1);   // BCB4 error   VC6 ok. G++ ok
    #009 list<int> ilist6(list_size, -6);  // BCB4 ok.     VC6 ok. G++ ok

    归纳:看来似乎 BCB4 不允许让 list<int> 只获得一个引数,也不允许
    list<int> 获得正值初值。很奇怪的行为。我疏忽了什么吗?

    2001/08/22 补充:
    BCB5[o]. 谢谢 Lianchao Xu




    ■C++ Primer p383 上
    主题:透过指向「函式指标阵列」的指标,唤起该阵列中的函式指标,
          其型式有简略式和明显式两种。
    测试结果:VC6[x]  BCB4[x]  G++[x]  (都不支援简略型式)
    实例:

    #001 #include <iostream.h>
    #002
    #003 typedef int (*PFV)();
    #004 int f1() { return 1; }
    #005 int f2() { return 2; }
    #006
    #007 PFV fFuncs[2] = { f1, f2 };
    #008 PFV (*pfFuncs)[2] = &fFuncs;
    #009
    #010 void main()
    #011 {
    #012   cout << fFuncs[0]() << endl;  // 1
    #013   cout << fFuncs[1]() << endl;  // 2
    #014
    #015   cout << pfFuncs[0]() << endl;  // 简略式,VC6[x]  BCB4[x]  G++[x]
    #016   cout << ((*pfFuncs)[1])() << endl;  // 2 (明显式)
    #017 }

    2001/08/22 补充:
    Lianchao Xu 建议我把:
    #008 PFV (*pfFuncs)[2] = &fFuncs;
    改为:
    #008 PFV *pfFuncs = fFuncs;

    再把:
    #015   cout << pfFuncs[0]() << endl;  // 简略式,VC6[x]  BCB4[x]  G++[x]
    #016   cout << ((*pfFuncs)[1])() << endl;  // 2 (明显式)
    改为:
    #015   cout << (*pfFuncs[0])() << endl;  // 1
    #016   cout << (*pfFuncs[1])() << endl;  // 2

    测试结果:VC6[o]  BCB4[o]  G++[o]
    谢谢。不过这并不是我的测试初衷。