是否要求标准库符合标准

Are standard library required to be standard conformant?

本文关键字:标准 是否      更新时间:2023-10-16

是否要求标准库符合标准?我有一种感觉,标准库并不符合标准。这种感觉的基础是编译器生成的错误消息。例如,有时GCC会给出以前缀__gxx开头的错误消息,以及许多我现在不记得的其他错误消息。但看到它们让我觉得这些都是编译器特有的消息,不同的编译器无法编译GCC提供的标准库,反之亦然。这是真的吗?

换句话说,这个问题可以被问到:

  • 一个编译器提供的标准库是否可以与其他编译器一起编译
  • 当我们说一个特定的编译器符合标准时,它自动是否意味着它附带的stdlib也符合标准?或者它只是意味着这个编译器可以编译我们程序员编写的符合标准的代码
  • 在使用不同编译器编译项目的项目中,我可以使用一个编译器提供的标准库吗可移植性与标准一致性相同吗

这些问题是从不同的角度来看待同一个问题。因此,请帮助我理解当我们说编译器X符合标准时,它到底意味着什么。

标准库是实现的细节。它甚至可能不是"编译"的,因为标准不要求它由"文件"[头]组成:

174)报头不一定是源文件,序列也不由<和>在标头名称中必须有效源文件名(16.2).

该标准谨慎地简化了对实现的要求,这样库就可以"内置"到编译器中(也称为内部函数)。例如,扩展std名称空间,或#定义标准库中使用的名称,会产生未定义的行为。

是的,标准库必须遵守标准,但这方面有相当大的灵活性。该标准不要求函数的特定实现,并且该实现可以自由添加内部函数、属性。。。只要满足要求。

请注意,对于符合标准的库和仅使用标准功能实现的库,存在不同的概念。

关于以下特定问题:

一个编译器提供的标准库是否可以与其他编译器一起编译?

有些会,有些不会。标准库的实现可以将编译器内部函数用于某些操作,这些操作的功能仅存在于一个平台中,而不存在于其他平台中。。。不过,一些STL实现可以使用不同的编译器进行编译,如STLPort、Dinkumware(也是VS中提供的,经过一些VS修改)

当我们说一个特定的编译器符合标准时,这是否意味着它附带的stdlib也符合标准?或者它只是意味着这个编译器可以编译我们程序员编写的符合标准的代码?

这意味着库必须是一致的,但同样,标准并没有强制实现库,这些可以使用非标准扩展等,这些扩展在一个编译器中有效,但在其他编译器中可能无效。例如,考虑shared_ptr的实现,引用计数必须以原子方式更新,但在当前标准中没有对整数的原子操作,因此必须根据非标准特性来实现。

在使用不同编译器编译项目的项目中,我可以使用一个编译器提供的标准库吗?可移植性和标准一致性相同吗?

不一定。

是否要求标准库符合标准?我有一种感觉,标准库并不符合标准。

根据定义,实现必须符合标准才能符合标准,是的。

否则,它不是C++标准库的实现,而是其他东西的实现。

当我们说一个特定的编译器符合标准时,这是否意味着它附带的stdlib也符合标准?

这将取决于措辞,不是吗?如果工具链声称包含标准库的实现,则可以合理地假设它是兼容的。编译器可执行文件本身是兼容的并不是一回事,除非库实现内置在编译器可执行程序中。

但这都只是文字游戏。

在使用不同编译器编译项目的项目中,我可以使用一个编译器提供的标准库吗?可移植性和标准一致性相同吗?

当然不是。两个一致的实现可能彼此完全不兼容。

例如,有时GCC会给出以前缀__gxx开头的错误消息,以及许多我现在不记得的其他错误消息。

没关系。工具链可以实现库,只要接口符合标准即可。该标准没有规定实现不能在其工作中使用符号__gxx


BTW

不过,它确实说程序员在某些情况下可能不使用带前导下划线的符号!

您不允许[lib.requirements]/[requirements]使用以下任何名称:

  1. 包含两个连续的下划线
  2. 以下划线开头,后跟大写字母
  3. 以下划线开头,位于全局命名空间中

此外,在C++0x中,保留了不以下划线开头的文字后缀。

库的面向用户的API应该是标准的;然而,并不需要实现。您看到了一个这样的例子,其中函数的标准版本被优化的变体替换(使用不同的名称,因为有时替换只有在某些情况下才可能,例如当可以证明适当的对齐时)。这也意味着一个编译器的标准库的实现可能无法由不同的编译器构建(这可能会导致移植时的自举问题,但这是另一个问题)。

当我们说编译器X是符合标准的时,它到底意味着什么

这意味着编译器为标准库提供了标准所依据的所有要求,并且实现本身符合标准中的所有要求。问题是,在通用接口之后,对标准库的"要求"相当自由。

标准库只需要满足最低限度的接口。在它的实现中,它可以做任何它想做的事情,因为,好吧,这就是实现,尽管我很确定有一些标识符限制等等来防止冲突。

标准库实现不必以任何方式进行移植。它们可以,但远非必然。

标准对标准库的接口而非实现进行了限制。它特意明确了标准库头可以做用户代码不能做的事情。。。例如,__MACRO__NAME__是为实现而保留的。显然,只有实现才能真正将所有这些函数和类型放入命名空间std.中

大多数情况下,可以编写一个"可移植"的实现。但它的性能可能会降低。。。作为一个简单的例子,考虑offsetof宏的传统实现。它通常涉及到取消引用空指针,这在形式上是未定义的行为,但因为实现知道其平台是如何工作的,所以没关系。可移植版本无法做到这一点,因此它必须实际创建所提供类型的新实例,以保持一切正常。

C++0x中相当多的类型特征可能需要编译器支持,这使得"可移植"实现变得困难和不可能。例如,没有标准的方法来分析任意类型是否为POD,这就是为什么boost::is_pod在某些平台上需要通过专业化来获得用户支持的原因。

还有一个考虑因素是,许多标准库不仅仅是头。其他部分可以用完全不同的语言编写。。。只要它们正确地连接在一起,就没关系。如果运行时是在Lisp中实现的,那么很明显,它将不是可以可靠地放入不同编译器工具链中的符合C++的代码。

一个编译器提供的标准库可以与另一个编译器一起编译吗编译器?

假设图书馆符合标准,是的(我知道这有点像鸡蛋和鸡)。

当我们说一个特定的编译器符合标准时它自动意味着stdlib它附带的也是是否符合标准?或者只是意味着此编译器可以编译编写的符合标准的代码我们,程序员?

是的,尽管我不知道有任何完全确认的编译器。请注意,作为程序员,符合我们的标准与标准库不同。例如,允许实现使用包含__(双下划线)的标识符。

我可以使用一个编译器提供的标准库吗使用不同编译器来编译项目?是便携性与是否符合标准?

您应该能够编译并使用这样的库。您几乎肯定无法使用任何已编译的库文件(静态或动态)文件,因为名称篡改会有所不同。