C ++ 11向后兼容性

时间:2013-11-01 15:04:33

标签: c++ gcc c++11 libstdc++

我可以使用c ++ 11中的任何内容并期望编译的二进制文件在旧系统上运行吗?如何判断c ++ 11的哪些部分是libstdc ++的一部分。那么实际编译成二进制文件的是什么?也许我不完全理解这些事情是如何起作用的。 c ++ 11是否符合ABI对旧库的要求?

清晰的例子:

假设我编译了一个使用auto的程序和基于for循环的新范围。这些东西似乎在具有旧c ++运行时的系统上工作,因为它们分解为在这些机器上有效的c ++。但是,使用像regex之类的东西应该在旧系统上中断,因为它不会在它们的运行时中。

我还没有测试过我的理论,因为我无法访问与c ++ 11兼容的编译器,而且谷歌的搜索也没有用。

2 个答案:

答案 0 :(得分:12)

你是对的。代码本身编译为可以在任何具有C ++编译器的平台上运行。新语言构造(范围for,新关键字如auto等)使用新编译器进行编译,以便在旧系统上正常工作。

但是,如果您尝试链接使用新符号(如正则表达式)的代码到旧库,那么无论您是静态链接还是动态链接,都会遇到问题,因为旧库没有新的符号。

假设您的代码使用了新符号:

  • 如果静态链接到旧库,则链接将失败,因为旧库中不存在新符号。
  • 如果您动态链接到旧库,您仍然会遇到链接器问题,因为该库不包含新符号。
  • 如果静态链接到新库,则生成的二进制文件将在较旧的系统上运行。
  • 如果动态链接到新库,则生成的二进制文件将在旧系统上运行(如果已有新库)或者使用二进制文件分发新库。
    • 但是,如果您尝试用旧的动态库替换新的动态库,它将无法链接到该库中的新符号,因为它们不存在。

答案 1 :(得分:3)

该标准对使用早期实现的任何内容都不做任何保证。规范定义了对实现的要求,并且实现要么符合这些要求,要么不符合要求。将部分C ++ 11实现与早期实现的部分拼接在一起是不可移植的,并且实际上不可能实现。

甚至编写一个完全不使用标准库且不使用任何C ++ 11特性的程序也不可能与C ++ 03实现的二进制文件ABI兼容。例如,实现者可能会利用新版本来更改调用约定。因此,通常将程序限制为auto和range-for等功能不一定与ABI兼容。

  

如何判断c ++ 11的哪些部分是libstdc ++的一部分。那么实际编译成二进制文件的是什么?

即使您不使用标准库的任何部分(您可以通过简单地不使用任何标头来保证这一点),这也不能保证编译的二进制文件不需要C ++ 11实现提供的运行时支持。可能依赖运行时支持的几个语言功能示例是异常和虚拟成员。

同样,运行时库支持不是C ++ 03和C ++ 11之间ABI不兼容的唯一原因。

  

c ++ 11是否符合ABI对旧库的要求?

不,我认为规范不需要阻止C ++ 03和C ++ 11实现共享ABI的任何内容。但是你想知道的是,较旧的规范是否足够严格,以至于较旧的实现必须具有可能由C ++ 11实现共享的ABI?答案就是没有,因此在实现C ++ 11时,实施者可能会被迫破坏ABI兼容性。


特定的C ++ 03和C ++ 11实现可以共同保证将C ++ 11编译的二进制文件与C ++ 03运行时支持混合,因此您可以使用它。但是,我不知道任何此类实现。

另一种选择是,不是试图混合C ++ 11和C ++ 03实现,而是C ++ 11实现可能能够创建自包含的二进制文件(或者主要是自包含的,因为在至少它必须依赖操作系统的系统调用ABI),不需要外部运行时支持。

您可以依赖的兼容性是源级别。您可以编写C ++ 11程序,也可以编译为C ++ 03,C ++ 03程序也可以编译C ++ 11,当然这种方法只限于C ++之间的最小公分母。 03和C ++ 11以及您将能够从中受益的唯一C ++ 11特性将是移动语义。