10

对于像 C++ 这样的语言,标准的存在是必须的。优秀的编译器会尽最大努力(至少是大多数优秀的编译器)来遵守。许多编译器都有语言扩展,有些是标准允许的,有些是不允许的。后一类的2个例子:

  1. gcc 的 typeof

  2. 微软的编译器允许纯虚函数声明同时具有纯说明符(=0)和定义(这是标准禁止的——我们不讨论为什么,这是另一个话题:)

(还有很多其他例子)

这两个示例在以下意义上都很有用:example1 是一个非常有用的功能,它将在 c++0x 中以不同的名称提供。example2 也很有用,微软决定不遵守没有意义的禁令。

我很感激编译器提供了语言扩展来帮助我们的开发人员进行日常工作。但这里有一个问题:不应该有一个选项,当设置时,它要求编译器尽可能地符合标准,无论他们是否同意标准。例如 Visual Studio 就有这样一个选项,称为禁用语言扩展。但是,嘿,他们仍然允许 example2。

我希望每个人都能正确理解我的问题。MSVC 允许 example2 是一件很棒的事情,我非常希望该功能成为标准。它不会破坏任何合规的代码,它不会做任何坏事。它只是不标准。

当禁用语言扩展设置为 true 时,您希望 microsoft 禁用 example2 吗?请注意,microsoft、example2 等这些词是占位符 :) 为什么?

再次,只是为了确保。关键点是:当编译器提供了一个非标准的更好的替代方案并且是甚至可能是标准的超集,因此不会破坏任何东西。

4

8 回答 8

7

标准合规性很重要,因为它使您的代码更易于维护。这体现在几个方面:

  • 从一个版本的编译器移植到另一个版本。我曾经不得不从 VC6 到 VC9 发布一个 120 万个 LOC 的应用程序。VC6 因严重不合规而臭名昭著,即使它是新的。即使在新编译器拒绝的最低警告级别上,它也允许不合规的代码。如果代码一开始就以更合规的方式编写,那么这个项目就不会(不应该)花费 3 个月的时间。

  • 从一个平台移植到另一个平台。正如您所说,当前的 MS 编译器具有语言扩展。其中一些由其他平台上的编译器共享,有些则不是。即使它们是共享的,行为也可能略有不同。编写兼容的代码,而不是使用这些扩展,可以让你的代码从一开始就正确。“移植”变得简单地把树拉下来并进行重建,而不是深入你的应用程序的内部,试图找出为什么 3 位是错误的。

  • C++ 是由标准定义的。编译器使用的扩展改变了语言。如果您使用标准 C++ 而不是您的编译器支持的方言,那么那些了解 C++ 但不了解编译器使用的方言的新程序员将更快上手。

于 2010-10-12T16:29:05.273 回答
4

首先,回复几个评论。有问题的 MS VC 扩展是这样的:

struct extension { 
    virtual void func() = 0  { /* function body here */ }
};

该标准允许您实现纯虚函数,但不能像这样“就地”实现,因此您必须改为这样编写:

struct standard { 
    virtual void func() = 0;
};

void standard::func() { ; }

至于最初的问题,是的,我认为编译器拥有一种尽可能准确地遵循(并强制执行)标准的模式是个好主意。虽然大多数编译器都有这个,但结果不一定像你/我想要的那样准确地表示标准。

至少在 IMO 看来,唯一的答案是让关心可移植性的人定期拥有(和使用)至少几个编译器。对于 C++,其中之一应该基于 EDG 前端;我相信它的一致性比大多数其他的要好得多。无论如何,如果您定期使用英特尔的编译器,那很好。否则,我建议您购买一份 Comeau C++;它只需 50 美元,它是最接近可用“参考”的东西。您也可以在线使用 Comeau,但如果您经常使用它,则值得拥有一份自己的副本。

听起来不像 EDG 或 Comeau shill 或任何东西,但即使您不太关心可移植性,我还是建议您获取一份副本——它通常会产生极好的错误消息。多年来,它干净、清晰的错误消息(全部由它们自己)节省了足够的时间来为编译器支付数倍的费用。

编辑:再看一遍,有些建议看起来已经过时了,尤其是对 EDG/Comeau 的建议。自从我最初写这篇文章以来的三年里,Clang 已经从纯粹的实验性发展到相当合理的生产使用。同样,gcc 维护者(IMO)在一致性方面也取得了长足的进步。

与此同时,Comeau 还没有发布他们的编译器的一个新版本,并且已经发布了 C++ 标准的新版本。结果,Comeau 现在相对于当前标准已经过时了(而且情况似乎在变得更糟,而不是更好——委员会已经批准了可能成为 C+ 的新标准的委员会草案+14)。

因此,虽然我当时推荐了 Comeau,但我今天(充其量)很难这样做。幸运的是,它提供的大多数优势现在在更主流的编译器中都可用——Clang 和 gcc 都提高了(基本上)如上所述的合规性,并且它们的错误消息也得到了显着改善(Clang 非常强调更好的错误消息,几乎从一开始就开始了)。

底线:我仍然建议至少安装两个可用的编译器,但是今天我可能会选择与最初编写此答案时不同的编译器。

于 2010-10-12T16:45:41.207 回答
3

从长远来看,“不破坏任何东西”是如此的滑坡,最好完全避免它。我公司的主要产品超过了几代编译器(第一次编写于 1991 年,使用 RW),并且每当需要迁移到更新的开发系统时,通过编译器扩展和安静的标准违规进行梳理需要付出很多努力。

但只要有一个选项可以关闭或至少警告“非标准扩展”,我就可以了。34、70、6。

于 2010-10-12T16:16:30.710 回答
3

我当然想要一个禁用语言扩展的选项来禁用所有语言扩展。为什么?

  • 所有选项都应该按照他们所说的去做。
  • 有些人需要开发可移植的代码,需要一个只接受语言标准形式的编译器。

“更好”是一个主观词。语言扩展对某些开发人员很有用,但对其他开发人员来说却使事情变得更加困难。

于 2010-10-12T16:25:34.050 回答
2

我认为,如果编译器想成为开发时使用的主要模式,那么编译器提供仅标准模式至关重要。当然,所有编译器都应该编译符合标准的代码,但如果它们不认为自己是主编译器,它们就不会扩展它们并不重要——例如,交叉编译器或用于更少的编译器几乎总是被移植到而不是被定位的流行平台。

扩展对任何编译器都很好,但是如果我需要它们就必须打开它们会很好。默认情况下,我更喜欢仅标准的编译器。

因此,考虑到这一点,我希望 MSVC 默认是标准的。与 gcc++ 相同。

统计数据:40、90、15

于 2010-10-12T16:27:09.367 回答
2

我认为标准合规性非常重要。

我一直认为源代码更适合人类读者而不是机器。因此,为了向读者传达程序员的意图,遵守标准就像说一种最低公分母的语言。

无论是在家里还是在工作中,我都使用 g++,并且为了严格遵守标准,我使用以下标志对其进行了别名。

-Wall -Wextra -ansi -pedantic -std=c++98

在严格的 ANSI/ISO上查看此页面

我不是标准专家,但这对我很有帮助。我编写了 STL 风格的容器库,它们在不同的平台上按原样运行,例如 32 位 linux、64 位 linux、32 位 solaris 和 32 位嵌入式 OSE。

于 2010-10-12T18:25:15.403 回答
2

考虑汽车上的指示灯(在某些司法管辖区称为“转向灯”);它们是确定某人将要关闭环岛的哪个方向的可靠方法......直到只有一个人根本不使用它们。然后整个系统崩溃。

IE 被允许document.someId用作document.getElementById('someId')...对,因为“它有效”。然后,突然之间,一千万个由此产生的网站完全不可移植。

标准对于互操作性很重要,如果您不遵循它们,那么拥有它们就毫无意义。

遵守标准的猎犬可能会因为“迂腐”而被憎恨,但实际上,除非每个人都效仿,否则您将永远面临可移植性和兼容性问题。

于 2013-05-01T09:29:45.040 回答
1

标准合规性的重要性取决于您要达到的目标。

如果您正在编写一个永远不会移植到其当前环境之外的程序(尤其是您不打算长期开发/支持的程序),那么它并不是很重要。任何工作,工作。

如果您需要您的程序长时间保持相关性,并且可以轻松移植到不同的环境,那么您将希望它符合标准,因为这是(或多或少)保证它可以在任何地方工作的唯一方法。

当然,诀窍是弄清楚你实际处于哪种情况。启动一个程序认为它是一个短期的hack是很常见的,后来发现它非常有用,以至于你仍在开发/维护它多年之后。在这种情况下,如果您在程序生命周期开始时没有做出任何短视的设计决策,那么您的生活将不会那么不愉快。

于 2010-10-12T16:24:53.803 回答