# 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++
- 在
MacOS
、iOS
上,我们使用的C++
库都是LLVM
项目实现的libc++(/usr/lib/libc++.dylib)
- 在
Android
上,我们使用的C++
库为LLVM
的libc++
(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),MSVC
,Xcode(OS)
,GCC(Unix)
, LLVM的clang
等,其中GCC
原本叫GNU C Compiler
,后来亦集成了其他语言的编译器,故称为GNU Compiler Collection
,其中g++
正是gcc
中的C++
编译器。LLVM
是与gcc
平行的模块化和可重用的编译器和工具链技术集合,clang
是LLVM
原生的C/C++/Objective-C
编译器。gcc
开源协议基于gplv3
,LLVM
开源协议基于Apache 2.0
,因此越来越多的厂商选择LLVM
。‵LLVM/GCC‵通常用于UNIX/MacOS
平台,MSVC
通常用于windows
平台。
如果想在windows
平台上使用GCC
,可以借助Cygwin
或MinGW
。
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 上运行。
# 参考资料
- 1.https://blog.csdn.net/lbw520/article/details/104585775 (opens new window)
- 2.https://zhuanlan.zhihu.com/p/291496862 (opens new window)
- 3.https://llvm.org/ (opens new window)
- 4.https://www.zhihu.com/question/20235742 (opens new window)
- 5.https://www.zhihu.com/question/22137175#:~:text=%E5%8C%BA%E5%88%AB%EF%BC%88%E5%B0%8F%E7%BB%93%EF%BC%89%EF%BC%9ACygwin%E6%98%AF,%E5%8F%AF%E4%BB%A5%E5%9C%A8Cygwin%20%E4%B8%8A%E8%BF%90%E8%A1%8C%E3%80%82 (opens new window)