【问题标题】:Is there "magic" in the STL? [closed]STL中有“魔法”吗? [关闭]
【发布时间】:2023-03-25 03:58:01
【问题描述】:

让我先解释一下我所说的“魔法”是什么意思。我将使用 Java 中的两个示例:

  1. 每个类都(直接或间接)继承Object 类。
  2. Java 不支持运算符重载,但 + 运算符是为 String 对象定义的。

这意味着不可能在 pure(*) Java 中实现 ObjectString 类。这就是我所说的“魔法”:要实现这些类,您需要编译器的一些特殊支持。

我一直喜欢 C++ 的一点是,据我所知,在 STL 中没有这样的“魔法”,也就是说,可以在纯 C++ 中实现 STL。

现在我的问题是:这是真的吗?还是 STL 的某些部分无法在纯 C++ 中实现,需要一些“魔法”/特殊编译器支持?


(*) “纯”是指不使用任何类库。

【问题讨论】:

  • 软件从不依赖魔法。然而,一个好的软件可以创造“魔法”的错觉
  • @Vite:我知道 STL 是标准的一部分,但就像我的脚注所说,纯粹是指没有任何库。
  • @Job:我认为混淆源于您使用了“魔法”这个词。将其描述为“需要编译器/语言支持”可能会消除大部分混淆。
  • 非常好的问题。 +1 :)
  • “任何足够先进的技术都与魔法无异。” (AC 克拉克)

标签: c++ stl std


【解决方案1】:

换句话说,是否对编译器进行了任何处理以允许 STL 工作所需的“特殊情况”?

没有。

使用模板的魔力,所有这些都被实现为“纯”C++ 代码。

编译器已经做了一些工作来改进 STL(我正在考虑各种优化),但除此之外,不,如果你真的想要,你可以编写整个 STL。有些人这样做了 - STLPort 是一个没有任何编译器制造商支持的实现。

【讨论】:

  • 嗯,大多数编译器都需要提高其标准合规性……但是,是的。
  • “使用 C++,魔法已经存在。”,+1
  • -1:这不再正确。查看其他答案。
【解决方案2】:

就像 gbjbaanb 所说的那样,STL 可以用纯 C++ 实现,而不依赖于任何类型的编译器“魔法”。

但是,如果您深入研究编译器的 STL 源代码,您可能会看到不标准的代码,或者您不应该自己编写的代码。

STL 可以完全用标准 C++ 实现,但这并不意味着编译器编写者不能偶尔使用编译器特定的扩展来改进它。例如,他们可能会插入非标准代码以确保更好的错误消息,或者可能会解决编译器中的一些缺陷,或者可能通过使用特定编译器的额外功能来启用特殊优化。

他们还始终使用您不允许使用的名称。例如,模板参数通常命名为 _Type,因为它以下划线开头,后跟大写字母,为实现保留。允许标准库使用它们,但你我都不允许。因此,如果您要编写自己的 STL 实现,则必须进行一些细微的更改,但这并不是因为任何魔法,只是为了避免标准库和用户代码之间的名称冲突。

【讨论】:

  • 非常好的答案!在决定接受哪个答案之前,我会让人们投票一段时间:-)
  • 请注意,“保留”名称由策略保留。这不是由编译器强制执行的。如果你愿意,你可以使用它们。正如 Jalf 所提到的,使用这些名称存在您的代码与编译器中包含的库(或其他人试图编译您的代码时的另一个库)发生名称冲突的风险,因此显然使用它们是一个坏主意。
  • 是的(我想我应该提到这一点,但现在你做得很好,所以给你 +1 :))
  • @Tomalak:真的吗?没有“编译器魔法”就无法实现 STL 的哪一部分?我可以提醒您您通常愚蠢的论点,即 STL 是 20 年前的 SGI 库吗?据我所知,没有改变。所以根据你的定义,我的回答绝对是正确的。对于我们其他人来说,这有点不确定,因为我们其他人使用“STL”来引用标准库的子集,并且 C++11 中有许多标准库功能需要编译器“魔法”。但是这些功能和“STL”部分之间是否有重叠?我不这么认为。
  • @jalf:是的。我在想 C++11 标准库,有点忘乎所以。适当地感到羞耻。
【解决方案3】:

正如其他人所说,STL 可以在纯标准 C++98 中实现。没有说的是,STL 的开发与 C++ 模板机制的开发是同步的,并且在很大程度上推动了某些特性的包含。我相信Argument Dependent Lookup (ADL, aka Koenig Lookup)、模板模板参数和默认模板参数都来到了C++,为Stepanov的STL开发服务。

因此,通过 STL,他们将魔法融入了语言本身。很高兴标准委员会认识到,如果这些特性对将成为标准库的东西有用,那么它们可能对我们其他人也有用!

【讨论】:

  • +1:感谢您的历史课!
  • 如果没有记错的话,ADL 是独立的(甚至早于标准化 STL 的提案)。
  • @Jerry--我怀疑你是对的。我现在没有任何相关的参考资料,所以我无法确认。也许有人可以挖掘出一份完整的清单?
【解决方案4】:

如果您所说的 STL 仅指 C++ 标准库的模板部分,那么完全有可能在没有任何“魔法”的情况下实现它。每个给定的实现是否真的使用任何“魔法”是一个不同的问题(在 STL 的某些部分,“魔法”会有所帮助,但不是绝对必需的)。

现在,如果您谈论的是整个 C++ 标准库,那么它确实有一点“魔力”。经典的例子是库提供的 ::operator new::operator delete 实现。在日常语言中,我们经常称它们为“可重载”,而正式它们是可替换。 C++ 语言不向用户提供此类功能。用户无法编写可替换函数。

另一个例子是offsetof 宏(继承自 C 标准库)。虽然它通常在“纯 C”中实现,但从迂腐的角度来看,流行的实现实际上是非法的(导致未定义的行为)。我还没有看到offsetof 的任何正式合法实现,所以我不确定它们是否可能。

另一个例子是(同样,继承自 C)用于处理可变参数的宏。它们显然不能用纯 C 或 C++ 实现。

【讨论】:

  • +1:可惜这个答案没有更多的赞成票。
  • '导致未定义的行为'......有很多地方可以做到这一点,operator++ 立即浮现在脑海中。所以这不是违法的,只是不明智的。当然,您不能替换默认的操作符 new,您可以为您的代码替换它的功能。在所有情况下,这个答案中没有什么是“魔法”——即你不能以任何形式使用的特殊东西,只有编译器编写者才能使用的特殊东西,其他人都没有。
  • @gbjbaanb:不正确。同样,标准库提供了::operator new(size_t) 的实现。您可以编写自己的::operator new(size_t) 实现,它将接管。不可能在用户代码中实现类似的东西。拥有两个具有相同签名的外部函数将导致错误(ODR 违规)。你可以为::operator new(size_t) 做到这一点是纯粹的“魔法”。
  • 我的回答中的一切都与魔法有关。在所有情况下都依赖于未定义的行为只能通过编译器细节来实现,这是一种魔法(我不明白你的 operator++ 参考是什么意思)。事实上,GCC 编译器从offsetof 的“未定义”实现切换到通过__builtin_offsetof 的显式神奇实现。
【解决方案5】:

我很确定某些type_traits 需要编译器魔法,例如has_trivial_constructorhas_virtual_destructoris_pod

【讨论】:

  • 好吧,如果这是真的,我当然想知道!有人知道这些是否可以用纯 C++ 实现吗?
  • 嗯,这些不在当前版本的标准中。它们计划包含在 C++0x 中(并且快速浏览草稿并没有产生任何关于如何实现它们的信息,所以你可能是对的,它们需要编译器魔法来实现——另一方面,它们唯一的那么目的是公开这个编译器魔法,以便普通开发人员可以使用它。他们不会像@Job 的 Java 示例那样把它留给自己。)
  • 我快速浏览了包含这些内容的 tr1。似乎该标准将无法在纯 C++ 中实现的事物定义为未定义的行为(如果我错了,请纠正我)。例如,is_pod 可能会返回假阴性。
  • 是的,在 C++0x 中会有一些类型特征需要编译器支持,但我不记得是哪些。那些需要编译器支持,因为没有办法在纯 C++ 中实现它们。
  • @Job:不过那是 TR1。 TR1 版本是仅限库的,因为它们基本上是从 Boost 中采用的。如果没有编译器支持,它们基本上不是最接近的。 C++0x 更进一步,提供了这些类型特征的版本,这些版本在所有情况下都可以正常工作。而这只能通过某种未指定形式的编译器支持来实现。
【解决方案6】:

std::initializer_list 需要编译器支持并且不能重新实现为另一个类(据我所知),但我不确定它是否重要,因为它在 c++0x 中。

【讨论】:

    【解决方案7】:

    C++0x 将标准化一些事实上的“神奇”类型特征。

    http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2984.htm

    “C++0x 的其他类型特征”

    这包含一些备注,例如“XXXX 被认为需要编译器支持”。

    另见

    http://gcc.gnu.org/onlinedocs/gcc-4.3.2/gcc/Type-Traits.html#Type-Traits

    http://msdn.microsoft.com/en-us/library/ms177194(v=vs.80).aspx

    【讨论】:

      【解决方案8】:

      正如“gbjbaanb”所说的那样,STL 的实现并不涉及魔法。它是用纯 C++ 编写的。您可以自己实现它,但它已作为库随时可用,让您的生活更简单。

      【讨论】:

        【解决方案9】:

        STL 是标准的(标准模板库)。该标准规定了 STL 实施的要求。从使用的角度来看,没有“魔法”,也没有您需要处理的特殊依赖项。它可以在任何主要的 C++ 编译器上使用,在这些编译器支持的所有平台上。

        【讨论】:

        • 但我的问题是STL本身的实现是否需要编译器的任何“魔法”。
        • @Job:它需要一个符合标准的良好编译器。
        • @Job:为了支持已经说过的话:编译器要求的Magic要符合STL的实现要求,这几乎是任何 C++ 编译器,而且,aehm,符合它。任何旧版本的 C++ 编译器都无法处理 STL,几乎所有较新的 C++ 编译器都可以。这就像共同进化
        • @chubsdad:符合标准的好的编译器可以被认为是魔法 :) ...
        • 任何足够先进的编译器都与魔法无异。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-02-06
        • 2010-11-08
        • 1970-01-01
        • 1970-01-01
        • 2010-09-26
        • 1970-01-01
        相关资源
        最近更新 更多