# 1.C++标准库

C++标准库是C++标准中规定的C++语言必须实现的库函数API,c++标准库的标准化始于1989年,由国际标准化组织(the International Organization for Standardization,ISO)推动制定。

ISO 14882标准中,在条款20到33和附加章节D中定义的C++应该实现的内容。
这部分内容是C++标准库应该要实现的内容。有了这个标准定义,世界上各个组织才能实现具体的C++标准库。C++标准库的实现必须依赖操作系统所提供的函数(读写文件,内存分配,线程创建等系统调用)来实现标准库,因此每一个操作系统都有自己的标准库实现,有时它是系统的一个核心部分,有时它作为附加部分——编译器,必须单独下载安装。

有影响力的组织及其实现有3个:GNU的libstdc++LLVM的libc++、其他。

  • GNU/Linux上,我们使用的C++库都是GNU实现的libstdc++(/usr/lib/gcc/x86_64-linux-gnu/9/libstdc++.so、/usr/lib/gcc/x86_64-linux-gnu/9/libstdc++.a),默认情况下,所有常用的Linux发行版都将使用libstdc++
  • MacOSiOS上,我们使用的C++库都是LLVM项目实现的libc++(/usr/lib/libc++.dylib)
  • Android上,我们使用的C++库为LLVMlibc++(NDK r18以前还是支持GNU的libstdc++的,在r18上被完全去除);注意这可不是系统库,你需要将库文件包含在apk中(Android上的系统库是/system/lib/libstdc++.so,这不是GNU的那个,只包含了最小的C++ runtime实现,如new delete等);
  • 在Windows中,标准库的实现一直严格绑定到Visual Studio中。他们称其为 C/C++ Run-time Library(CRT),其中同时实现了C和C++标准库

g++编译时带上-v参数,日志就会清楚的显示编译的时候默认使用了什么库。

g++ -v preprocessor_test.cpp -o main
  • 动态编译

程序编译完成之后已经成为了ELF文件,这个时候它就可以在Linux上被执行了,由于我们的程序默认链接的是动态库,因此在运行时会对包括C++标准库在内的一些动态库产生依赖,使用ldd命令可以看到这些依赖:

ldd main
        linux-vdso.so.1 (0x00007ffde61c6000)
        libstdc++.so.6 => /lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f94c658e000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f94c639c000)
        libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f94c624d000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f94c67ba000)
        libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f94c6232000)
  • 静态编译

如果想静态链接的话,加上-static关键字,

g++ -v -static gemfield.cpp -o gemfield

如此一来,这个库在运行的时候就不依赖任何库了,但不推荐这么做,bug fix, 物理内存占用、安全相关功能将无法使用等。

不是每个系统上的C++编译都使用了标准的C++特性。这里的系统主要是手机操作系统,比如Android。ndk-build可能默认将异常、RTTI等功能停用

  • 所有的Linux库都必须以lib开头

不使用标准库十分简单:只要不引入任何它的头文件即可,在为嵌入式系统编程的时候也不会想包含标准库。

总结:C++标准库是编译器或操作系统对ISO C++标准的实现,其实现涉及到系统调用、汇编编写硬件接口程序等,因此,不同平台的C++标准库实现方式不同,但对于程序开发者无感知,使用标准库可开发跨平台可移植的程序。

# 2.C++编译器

总结:C++编译器也是对C++标准的一种实现,作用是将开发者编写的C++源码转换成机器可执行的二进制程序。

我们常用的编译器一般有Visual Studio(Windows),MSVCXcode(OS)GCC(Unix), LLVM的clang等,其中GCC 原本叫GNU C Compiler,后来亦集成了其他语言的编译器,故称为GNU Compiler Collection,其中g++正是gcc中的C++编译器。LLVM是与gcc平行的模块化和可重用的编译器和工具链技术集合,clangLLVM原生的C/C++/Objective-C编译器。gcc开源协议基于gplv3,LLVM开源协议基于Apache 2.0,因此越来越多的厂商选择LLVM‵LLVM/GCC‵通常用于UNIX/MacOS平台,MSVC通常用于windows平台。

如果想在windows平台上使用GCC,可以借助CygwinMinGW

引用自 (opens new window)

  • Cygwin的目的是提供运行于 Windows 平台的类 Unix 环境(以 GNU 工具为代表),为了达到这个目的,Cygwin 提供了一套抽象层dll,用于将部分 Posix 调用转换成 Windows 的 API 调用,实现相关功能。

  • MinGW,Minimalist GNU for Windows,用于开发原生(32位) Windows 应用的开发环境。它主要提供了针对 win32 应用的 GCC、GNU binutils 等工具,以及对等于 Windows SDK(的子集)的头文件和用于 MinGW 版本 linker 的库文件(so、a等,而不是 VC 的 lib)。MinGW 能够替代 cl 用于编译不包含 MFC 的、以 WinSDK 为主的 Windows 应用,并且编译出来的应用不依赖于第三方的模拟层支持,其运行时为大部分 Windows 标配的 msvcrt (故称原生 Windows 应用)。除此之外,MinGW 也支持 GCC 支持的其他语言。因为这些原因,MinGW 被许多 Linux 上发展起来的开发工具选择为 Windows 版本的默认编译器,例如 CodeBlocks,例如 DevC++。

  • MSYS 是用于辅助 Windows 版 MinGW 进行命令行开发的配套软件包,提供了部分 Unix 工具以使得 MinGW 的工具使用起来方便一些。如果不喜欢庞大的 Cygwin,而且使用不多,可以试试。不过喜欢完整体验、不在乎磁盘占用等等,还是推荐 Cygwin 而不是 MSYS。

总结:

  • 区别:Cygwin是模拟 POSIX 系统,源码移植 Linux 应用到 Windows 下;MinGW 是用于开发 Windows 应用的开发环境。

  • 联系:均提供了部分 Linux 下的应用,多跑在 Windows 上;MinGW 作为 Cygwin 下的软件包,可以在 Cygwin 上运行。

(adsbygoogle = window.adsbygoogle || []).push({});

# 参考资料