1 C++常见编译器介绍
C++语言的编译器是将C++源代码转换为机器可执行代码的工具。以下是一些广泛使用的C++编译器:
-
GNU Compiler Collection (GCC):GCC是一个自由软件编译器集合,支持C、C++、Objective-C、Fortran、Ada和Go等多种编程语言。它是最流行的开源C++编译器之一,广泛用于各种操作系统和平台上。
-
Clang:Clang是基于LLVM的C、C++、Objective-C和Objective-C++编译器前端。它以其出色的错误消息、性能以及丰富的源代码静态分析工具而闻名。
-
Microsoft Visual C++ (MSVC):MSVC是微软开发的C++编译器,与Visual Studio集成。它为Windows平台提供了强大的开发工具,包括集成开发环境、调试器和性能分析工具。
-
Intel C++ Compiler (ICC):由Intel开发的C++编译器,提供了自动向量化和并行化等高级优化特性,特别适用于需要高性能计算的应用。
-
Borland C++:Borland系列编译器(包括早期的Turbo C++)曾经非常流行,尤其是在DOS和Windows 3.1时代。Borland C++ Builder Compiler是其中的一个产品,它包括了对ANSI/ISO C++语言的支持。
-
Watcom C++:Watcom C++是一个历史悠久的编译器,以其在DOS时代的高效编译而著称。现在,Watcom C++作为Open Watcom开源包发行,支持多种操作系统。
-
Digital Mars C++ Compiler:Digital Mars是一款高性能的C和C++编译器,它包括了一个集成开发环境和多种编程工具,如反汇编器和资源编译器。
-
Tiny C Compiler (TCC):TCC是一个小型的C语言编译器,虽然它主要用于C语言,但也支持一些C++特性。
-
Code::Blocks:Code::Blocks是一个轻量级的C++集成开发环境,它支持多种编译器,包括GCC和Clang,并且提供了代码自动补全、调试和版本控制等功能。
-
Qt Creator:基于Qt框架的C++集成开发环境,它提供了一套完整的工具集,用于开发跨平台的应用程序。
这些编译器各有特点,其中,GCC和Clang因其开源和跨平台特性在许多Linux发行版中被广泛采用;而MSVC则在Windows平台上提供了优秀的集成开发体验。
扩展知识:
g++
和 gcc
是GNU编译器集合(GNU Compiler Collection,简称GCC)中的两个相关但独立的编译器,它们都用于从源代码生成可执行程序,不过它们分别针对不同的编程语言。
-
gcc:
-
gcc
是GNU C Compiler的缩写,它是GCC中用于编译C语言程序的编译器。 -
它支持多种与C语言相关的语言标准,如ANSI C(ISO C89)、ISO C99、ISO C11等。
-
gcc
也可以用于编译C++程序,但需要链接C++标准库。在某些系统中,可能存在一个名为c++
的符号链接到g++
,这样你就可以使用c++
命令来编译C++程序。
-
-
g++:
-
g++
是GNU C++ Compiler的缩写,它是GCC中用于编译C++程序的编译器。 -
它不仅包含了
gcc
的功能,还增加了对C++特定特性的支持,如类、模板、异常处理等。 -
g++
默认链接C++标准库(如libstdc++),而gcc
默认链接C标准库。
-
因此,它们之间的具有以下关系:
-
相同之处:
-
它们都是GCC编译器集合的一部分。
-
它们共享底层的优化器和代码生成器,因此对于底层的C代码,两者在优化和生成的机器代码方面可能是相同的。
-
-
不同之处:
-
gcc
主要用于编译C语言程序,而g++
用于编译C++程序。 -
g++
在编译C++程序时会启用C++语言特性,并链接C++标准库,而gcc
需要额外指定链接C++标准库的选项(如-lstdc++
)。 -
g++
支持C++特有的编译选项和编译阶段,如模板元编程、名称修饰(name mangling)和RTTI(运行时类型识别)。
-
2 g++编译器简介
2.1 g++编译器安装
g++
是GNU编译器集合中用于编译C++程序的编译器。如果Linux操作系统没有安装g++
的话,以Ubuntu为例,参考以下命令安装g++
whccf@whccf-VirtualBox:~$ g++
Command 'g++' not found, but can be installed with:
sudo apt install g++
whccf@whccf-VirtualBox:~$ sudo apt install g++
[sudo] whccf 的密码:
正在读取软件包列表... 完成
正在分析软件包的依赖关系树
正在读取状态信息... 完成
下列软件包是自动安装的并且现在不需要了:
gir1.2-goa-1.0 gir1.2-snapd-1
使用'sudo apt autoremove'来卸载它(它们)。
将会同时安装下列软件:
g++-7 libstdc++-7-dev
建议安装:
g++-multilib g++-7-multilib gcc-7-doc libstdc++6-7-dbg libstdc++-7-doc
下列【新】软件包将被安装:
g++ g++-7 libstdc++-7-dev
升级了 0 个软件包,新安装了 3 个软件包,要卸载 0 个软件包,有 0 个软件包未被升级。
需要下载 11.2 MB 的归档。
解压缩后会消耗 42.4 MB 的额外空间。
您希望继续执行吗? [Y/n] y
获取:1 http://mirrors.tuna.tsinghua.edu.cn/ubuntu bionic-updates/main amd64 libstdc++-7-dev amd64 7.5.0-3ubuntu1~18.04 [1,471 kB]
获取:2 http://mirrors.tuna.tsinghua.edu.cn/ubuntu bionic-updates/main amd64 g++-7 amd64 7.5.0-3ubuntu1~18.04 [9,697 kB]
获取:3 http://mirrors.tuna.tsinghua.edu.cn/ubuntu bionic-updates/main amd64 g++ amd64 4:7.4.0-1ubuntu2.3 [1,568 B]
已下载 11.2 MB,耗时 2秒 (5,127 kB/s)
正在选中未选择的软件包 libstdc++-7-dev:amd64。
(正在读取数据库 ... 系统当前共安装有 176694 个文件和目录。)
正准备解包 .../libstdc++-7-dev_7.5.0-3ubuntu1~18.04_amd64.deb ...
正在解包 libstdc++-7-dev:amd64 (7.5.0-3ubuntu1~18.04) ...
正在选中未选择的软件包 g++-7。
正准备解包 .../g++-7_7.5.0-3ubuntu1~18.04_amd64.deb ...
正在解包 g++-7 (7.5.0-3ubuntu1~18.04) ...
正在选中未选择的软件包 g++。
正准备解包 .../g++_4%3a7.4.0-1ubuntu2.3_amd64.deb ...
正在解包 g++ (4:7.4.0-1ubuntu2.3) ...
正在设置 libstdc++-7-dev:amd64 (7.5.0-3ubuntu1~18.04) ...
正在设置 g++-7 (7.5.0-3ubuntu1~18.04) ...
正在设置 g++ (4:7.4.0-1ubuntu2.3) ...
update-alternatives: 使用 /usr/bin/g++ 来在自动模式中提供 /usr/bin/c++ (c++)
正在处理用于 man-db (2.8.3-2ubuntu0.1) 的触发器 ...
whccf@whccf-VirtualBox:~$ g++ -v
Using built-in specs.
COLLECT_GCC=g++
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/7/lto-wrapper
OFFLOAD_TARGET_NAMES=nvptx-none
OFFLOAD_TARGET_DEFAULT=1
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 7.5.0-3ubuntu1~18.04' --with-bugurl=file:///usr/share/doc/gcc-7/README.Bugs --enable-languages=c,ada,c++,go,brig,d,fortran,objc,obj-c++ --prefix=/usr --with-gcc-major-version-only --program-suffix=-7 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-bootstrap --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-libmpx --enable-plugin --enable-default-pie --with-system-zlib --with-target-system-zlib --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
Thread model: posix
gcc version 7.5.0 (Ubuntu 7.5.0-3ubuntu1~18.04)
2.2 g++常用命令
g++
常用命令如下表所示:
功能/选项 | 描述 | 示例 |
---|---|---|
基本编译 | ||
-c | 只编译不链接,生成目标文件(.o ) | g++ -c source.cpp |
-o | 指定输出文件名 | g++ source.cpp -o output |
多文件编译 | ||
多个源文件 | 同时编译多个源文件 | g++ source1.cpp source2.cpp -o output |
头文件和库 | ||
-I | 指定头文件搜索路径 | g++ -I /path/to/headers source.cpp -o output |
-L | 指定库文件搜索路径 | g++ -L /path/to/libs source.cpp -o output |
-l | 链接指定库(无需指定文件扩展名) | g++ -lmylibrary source.cpp -o output |
调试和优化 | ||
-g | 添加调试信息 | g++ -g source.cpp -o output |
-O | 优化等级(0-3),默认不优化 | g++ -O2 source.cpp -o output |
-Og | 优化并保留调试信息 | g++ -Og source.cpp -o output |
警告和错误 | ||
-Wall | 显示所有标准警告 | g++ -Wall source.cpp -o output |
-Wextra | 显示额外的警告 | g++ -Wextra source.cpp -o output |
-Werror | 将警告视为错误 | g++ -Werror source.cpp -o output |
标准和方言 | ||
-std | 指定 C++ 标准(如 C++11, C++14, C++17, C++20) | g++ -std=c++17 source.cpp -o output |
-pedantic | 严格按照标准进行检查 | g++ -pedantic source.cpp -o output |
链接器选项 | ||
-static | 使用静态库链接 | g++ -static -lmylibrary source.cpp -o output |
-shared | 生成共享库 | g++ -shared -o libmylibrary.so source.cpp |
其他 | ||
-v | 显示详细的编译过程 | g++ -v source.cpp -o output |
-E | 仅进行预处理,不编译或链接 | g++ -E source.cpp -o output.i |
-S | 生成汇编代码 | g++ -S source.cpp -o output.s |
2.3 g++告警选项
g++
常用告警选项如下表所示:
告警选项 | 描述 |
---|---|
-Wall | 启用一组常用的告警选项,包括一些常见的编程错误。 |
-Wextra | 提供比 -Wall 更严格的告警集,包括一些额外的潜在问题。 |
-Wpedantic | 启用所有符合C++标准的告警,要求代码严格遵循C++标准。 |
-Wconversion | 告警所有可能的类型转换问题。 |
-Wsign-compare | 当使用有符号和无符号整数进行比较时发出告警。 |
-Wshadow | 如果局部变量遮蔽了外部变量,发出告警。 |
-Wunused | 告警所有未使用的变量、函数和参数。 |
-Wunused-result | 如果函数返回结果没有被使用,发出告警。 |
-Winit-self | 当变量被初始化为自己的值时,发出告警。 |
-Wmissing-include-dirs | 如果包含了不存在的目录,发出告警。 |
-Wimplicit-fallthrough | 在switch语句中,如果没有明确标记break或continue,发出告警。 |
-Wformat | 检查printf和scanf等格式化字符串函数的参数类型和格式字符串是否匹配。 |
-Wself-move | 当对象被移动到自身时,发出告警。 |
-Wdouble-promotion | 当浮点数被隐式提升为双精度时,发出告警。 |
3 C++第一份代码"hello,world"
-
VS Code编写"hello, world",源代码文件名helloworld.cpp
#include <iostream>
int main()
{
// 输出 "Hello, World!"
std::cout << "Hello, World!" << std::endl;
return 0;
}
-
Linux环境下,使用g++编译并生成helloworld的可执行程序
g++ -o helloworld helloworld.cpp
-
Linux环境下,执行helloworld可执行程序
./helloworld
4 代码分析
-
预处理指令
#include <iostream>
-
#include
是一个预处理指令,它告诉编译器在编译之前要包含指定的头文件。 -
<iostream>
是一个标准库头文件,它包含了C++标准库中关于输入/输出流的对象和函数的声明。<iostream>
提供的std::cout
对象,它代表标准输出流,用于向控制台输出数据。
-
-
主函数
int main()
-
main
函数是C++程序的入口点,即程序从这里开始执行。 -
int
是main
函数的返回类型,表示main
函数将返回一个整数。 -
在操作系统中,这个返回值通常用于指示程序是否成功执行。通常,返回
0
表示程序成功执行,而非零值表示出现错误。
-
-
输出语句
std::cout << "Hello, World!" << std::endl;
-
std::cout
是一个输出流对象,用于向标准输出(通常是控制台或终端)发送数据。 -
<<
是一个插入运算符,用于将数据发送到输出流。 -
"Hello, World!"
是一个字符串字面量,表示要输出的文本内容。 -
std::endl
是一个流操纵符,它向输出流插入一个换行符,并刷新输出缓冲区,确保数据立即被显示在控制台上。
-
-
返回值
return 0;
-
return
语句用于从函数中返回一个值。 -
在
main
函数中,return 0;
表示程序成功执行,并返回状态码0
。
-