【问题标题】:How important is standards-compliance?标准合规性有多重要?
【发布时间】:2011-04-24 09:58:29
【问题描述】:

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

  1. gcc 的类型

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

(还有很多其他的例子)

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

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

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

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

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

【问题讨论】:

  • example2 在 g++ 中也是允许的,不仅是 MSVC。
  • 我很确定标准允许定义纯虚拟。 en.wikipedia.org/wiki/Virtual_function “虽然纯虚方法通常在声明它们的类中没有实现,但 C++ 中的纯虚方法允许在其声明类中包含实现,提供派生类可以在适当时委托给的后备或默认行为。 ",但你的问题仍然很有趣。
  • 说“它没有坏处”非常简单。如果您默认允许不合规代码,那么人们倾向于使用它,然后最终编写的合规代码很少。诚然,它不会影响那些决心编写 100% 合规代码的人,但它确实意味着任何不太了解合规意味着什么的人最终都会编写不合规的代码,甚至没有意识到它。然后在 5 年后,当他们的编译器更新为更严格,或者当他们必须将他们的软件移植到另一个平台时,他们将面临很多痛苦。
  • @Lou,是的,定义是允许的,但作为一个单独的声明,不在你写 =0 的同一个声明中。离顶:)
  • 该主题有 2 票未投票。你能告诉我这个话题有什么可怕的地方值得结束吗?不要这么牛逼:)))

标签: c++ standards-compliance


【解决方案1】:

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

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

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

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

【讨论】:

  • 我曾经不得不从 VC6 到 VC9 发布一个 120 万个 LOC 的应用程序。 天哪。
  • 我认为需要提及的是,特别是对于模板代码,使用至少两个编译器进行测试是个好主意。在 Windows 中,我为此使用 g++。 Comeu Online还可以方便地检查小代码sn-ps的有效性;但是我没有使用完整的 Comeau 编译器的经验。
  • 我很高兴地说,我从来不需要将 120 万行代码的应用程序从 VC6 移植到 VC9。不过我可以想象那种痛苦。 ;)
  • <boasting> 我是一个小组的一员,该小组在十年内将一个项目从 VC6/CW6/GCC2.x 上的几个 10kLoC 发展到 VC9/GCC4 上的多 MLoC。我学会了痛恨VC6。 (我喜欢MWRon。)</boasting>
  • 只是为了纠正一个小问题:VC 6 “即使是新的也非常不合规”。相反,当它是新的时,它异常好——事实上,当时唯一明显更好的是EDG衍生产品。问题是它在大约 4 年的时间里一直是微软的“当前”编译器,在标准最终确定之前开始刚刚。完成该标准的活动一连串,不久之后,大多数其他编译器都非常努力地满足新标准 - 但 MS 什么也没做
【解决方案2】:

首先回复几位cmets。有问题的 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 已经几乎从一开始就非常强调更好的错误消息)。

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

【讨论】:

  • 我是唯一一个认为合规性不仅对移植而且对学生/教育目的都是必要的人吗?也就是说,我在标准中阅读了一段非常困难的段落,我以为我理解了,现在我想在真正的编译器上检查它......同意/不同意?
  • 任何复杂、成熟的软件,都有用户资料和要求。即使是同一类别的软件也可能有不同的目标用户,因此有不同的需求。如果您想成为一名优秀的学生编译器,那么是的,这是要求合规的一个很好的理由。编译器的正常用例是创建生产软件,而不是检查标准文档。
  • 话虽如此,我可以想象一个编译器的唯一目的是检查合规性,提供非常好的描述性警告和错误,并且可能不提供最优化的代码。有些产品,比如 Lint,可以做到这一点并且根本不生成代码——尽管它们对这种合规性检查很有用。出于这个原因,我使用 LLVM 的静态分析器(因为我不相信我的编译器会保持我的标准)
  • @Lou:好主意。但根本不生成代码意味着它只检查语法,而不是语义。
  • 题外话:恭喜你成为Legendary
【解决方案3】:

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

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

【讨论】:

    【解决方案4】:

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

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

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

    【讨论】:

    • MSVC 中有一个,至少从版本 8 开始。但是,启用它会阻止您编译最轻微的 Windows 代码。
    【解决方案5】:

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

    扩展适用于任何编译器,但如果我需要它们时必须打开它们会很好。默认情况下,我更喜欢纯标准编译器。

    因此,鉴于此,我希望 MSVC 在默认情况下仅是标准的。与 gcc++ 相同。

    统计数据:40、90、15

    【讨论】:

      【解决方案6】:

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

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

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

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

      Strict ANSI/ISO查看此页面

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

      【讨论】:

      • 不幸的是 -ansi -pedantic -std=c++98 没有给你严格的标准一致性
      【解决方案7】:

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

      当他们允许 document.someId 用作 document.getElementById('someId') 的快捷方式时,它并没有“伤害任何人”或明显“破坏任何东西”在 IE 中......但是,它确实产生了整整一代的程序员甚至书籍,他们因此认为它是好的和正确的,因为“它有效”。然后,突然之间,一千万个由此产生的网站完全不可移植。

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

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

      【讨论】:

      • 如果人们使用document.someId 而标准没有这样的功能 - 这意味着标准已经过时,msdn 成为事实上的标准。
      • 您似乎提出了一个关于标准化常见做法(ANSI/ISO C、C++98)和提前标准化(HTML5、C++11 的某些部分)的完全正确的观点。前者是非常可取的,后者更值得商榷(而且效率较低)。但是我看不出这与问题有何关系(尽管我不是反对者)。
      【解决方案8】:

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

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

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

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

      【讨论】:

      • 其实你是对的,但是你是站在开发者的角度说的。我们必须从编译器厂商的角度来看
      • @Armen:编译器是为开发人员构建的,而不是编译器供应商。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-12-07
      • 2011-02-24
      • 1970-01-01
      • 2013-09-21
      • 2018-09-06
      相关资源
      最近更新 更多