8

这是一个非常无知的问题,但是:

我想开始使用 C++11。我可以继续使用用旧的 gcc 4.2.1 编译器编译的大量库,还是需要用新的编译器重新编译它们?我认为(或希望)答案是否定的,但我只是一个涉足者。

这样我至少可以消除我的部分无知,你能解释一下为什么在这两种情况下?

谢谢

4

5 回答 5

9

是的你应该。

较弱的原因不是二进制兼容性,问题在于期望。启用 C++11 的编译器将期望许多功能可用(在它们之间移动构造函数)并在适当时使用它们。这只是冰山一角,还有其他几个不兼容的地方(auto以及0它与指针的交互......)。

这意味着根据 C++11 标准,标头中的任何内联方法都可能突然被不同地解释。

更有力的原因是每个版本的编译器都有自己的标准库实现。您真的不想开始混合各种版本,尤其是当它们经历了如此重大的变化时(再一次,右值引用......)。

相信我,现在重新编译更简单,而不是那种烦人的想法,即出现的每个错误都可能是由于新旧库之间的不兼容......

于 2012-02-23T07:29:20.227 回答
3

答案完全取决于您的库的 API 及其实现依赖项。

保证您不需要重新编译的条件是:

-- 您的库在其公共 API 中不使用 C++ 特定功能。

这意味着:

  1. 您的库不提供类/类模板/函数模板/其他 C++ 特定的东西。

  2. 您不接受/返回 C++ 类到/从您的库函数。

  3. 您不通过引用传递函数参数。

  4. 您不提供具有 C++ 特定实现的公共内联函数。

  5. 你不会从你的函数中抛出异常。

  6. 您没有(因为您没有理由)在公共标头中包含 C++ 特定的库标头。(如果你确实包含它们不会有什么坏处,但如果你删除这些包含,一切都必须是好的。它就像一个指示器。)

-- 您的库仅依赖于与新构建环境中可用的库二进制兼容的库。

如果不满足这些条件,则无法保证您的库将正常工作。在大多数情况下,重新编译比确保一切正常工作要容易得多。

无论哪种方式,如果您要制作满足上述条件的二进制兼容 API,那么设计和实现 C 语言 API 会好得多。这样您就可以自动满足上述条件,而不会陷入编写 C 风格的 C++ 代码的罪恶之中。

于 2012-02-23T08:13:54.063 回答
3

这是一个编译器问题。例如,如果您有一个编译器同时支持C++03C++11依赖于编译器开关,那么您很可能可以混合库。C++11 中没有什么新东西会强制与 C++03 不兼容。

但是,您提到您的库是使用 GGC 4.2.1 编译的。由于当时 C++11 只是一个想法,因此很可能当时的 GCC 是以与 C++11 不兼容的方式实现的。

例如,std::list::size()在 C++11 中必须是 O(1),但在 C++03 中可能是 O(N)。当时 GCC 选择了 O(N) 实现,不知道未来的需求。当前的 GCCstd::list::size实现与 C++11 和 C++03 兼容,因为 O(1) 优于 O(N)。

于 2012-02-23T11:47:04.837 回答
1

您可以在不重新编译的情况下使用 C++11 的大部分内容(假设 ABI 兼容),但至少对我而言,一个特别重要的部分将无法被已编译的代码访问 - 移动语义。

只需使用 C++11 编译器(最好是 C++11 标准库)重新编译,移动语义就可以使您的代码更快。

还有其他原因。也许您的首选库自从您上次编译它以来已经支持 C++11,并且如果使用 C++11 编译器编译,它现在更高效、更安全或更易于使用?

对于您自己的库,使用 C++11 您肯定可以使其更高效、更安全且更易于使用吗?:)

于 2012-02-23T07:27:58.387 回答
1

如果您对已编译代码的接口使用任何由 C++11 修改的模板,那么是的,您必须重新编译。否则,您可能可以继续使用您的旧库(除非编译器提供商也决定同时更改 ABI,因为这是修复长期存在的 ABI 错误的好机会,否则这些错误通常会因为二进制文件而无法修复不兼容)。

于 2012-02-23T07:34:47.950 回答