Ubuntu 22.04 G++ 安装与命令参数详解
Ubuntu 22.04 下 GNU C++ 编译器 g++(11.4.0)的在线与离线安装、四阶段编译、标准/优化/警告参数、类模板重载、静态库与共享库制作的完整实测详解
Ubuntu 22.04 G++ 安装与命令参数详解
目标:在 Ubuntu 22.04 x86_64 环境从零完成 GNU C++ 编译器 g++ 的安装与配置,并逐一演示其核心命令与参数的真实回显。本文所有命令均在 Ubuntu 22.04.5 LTS x86_64 环境实测通过,输出逐行照抄真实结果。
一、环境信息
| 项目 | 值 |
|---|---|
| 操作系统 | Ubuntu 22.04.5 LTS(jammy) |
| 系统架构 | x86_64(amd64) |
| 包管理器 | apt(底层 dpkg) |
| 编译器驱动 | g++(gcc 的 C++ 前端驱动) |
| g++ 二进制版本 | 11.4.0(g++ (Ubuntu 11.4.0-1ubuntu1~22.04.3) 11.4.0) |
| 软件包版本 | 4:11.2.0-1ubuntu1(g++ 为元包,实际编译器来自 g++-11 / gcc-11) |
| 目标三元组 | x86_64-linux-gnu |
| 默认标准 | gnu++17(GNU 扩展的 C++17) |
| 软件源 | http://archive.ubuntu.com/ubuntu/ jammy |
💡 说明:Ubuntu 的
g++是一个「元包」(版本 4:11.2.0-1ubuntu1),它依赖g++-11、gcc-11、cpp-11等具体编译器包;g++ --version显示的是真正参与编译的 gcc-11 系列版本 11.4.0。两者版本号不同属正常现象。
二、工具概述
g++ 是 GNU 编译器套件(GCC,GNU Compiler Collection)面向 C++ 语言的驱动程序。它与 gcc 同源,但存在两个关键区别:
- g++ 会自动把
.cpp、.cc、.cxx等扩展名的源文件按 C++ 语言处理; - g++ 在链接阶段会自动链接 C++ 标准库
libstdc++,因此std::cout、std::string、STL 集合等符号无需手工添加库参数。
g++ 的核心功能是把 C++ 源码经过「预处理 → 编译 → 汇编 → 链接」四个阶段,最终生成可执行文件;同时支持生成静态库(配合 ar)与共享库(配合 -shared/-fPIC)。
典型使用场景:
- 编写和编译 C++ 程序(面向对象、STL、模板编程);
- 按
-std=c++11/14/17/20指定语言标准编译; - 通过
-O2/-O3做优化,-g生成调试信息配合 gdb 调试; - 通过
ar打包静态库、-shared -fPIC构建共享库; - 用
-MM/-M生成 Makefile 依赖关系。
💡 说明:g++ 依赖 gcc、cpp、binutils 等组件,安装 g++ 时 apt 会自动拉齐这些依赖。
三、在线安装方案
3.1 基础环境确认
Ubuntu 22.04 服务器以 root 或具有 sudo 权限的普通用户登录。普通用户执行安装命令时需要加 sudo 前缀,root 用户直接执行。先确认系统版本与架构:
cat /etc/os-release | head -3
真实回显:
PRETTY_NAME="Ubuntu 22.04.5 LTS"
NAME="Ubuntu"
VERSION_ID="22.04"
查看架构:
uname -m
真实回显:
x86_64
3.2 软件源配置
Ubuntu 22.04 默认软件源配置文件为 /etc/apt/sources.list,其中启用了 main、universe、multiverse 等组件。查看当前生效的源:
cat /etc/apt/sources.list | grep -v "^#"
真实回显:
deb http://archive.ubuntu.com/ubuntu/ jammy main restricted
deb http://archive.ubuntu.com/ubuntu/ jammy-updates main restricted
deb http://archive.ubuntu.com/ubuntu/ jammy universe
deb http://archive.ubuntu.com/ubuntu/ jammy-updates universe
deb http://archive.ubuntu.com/ubuntu/ jammy multiverse
deb http://archive.ubuntu.com/ubuntu/ jammy-updates multiverse
💡 说明:若服务器无法访问外网,可将
archive.ubuntu.com替换为国内镜像(如 mirrors.aliyun.com、mirrors.tuna.tsinghua.edu.cn),保持 jammy 版本代号不变。
刷新软件包索引:
apt update
真实回显(末尾):
Reading package lists...
Building dependency tree...
Reading state information...
8 packages can be upgraded. Run 'apt list --upgradable' to see them.
3.3 安装 g++
执行在线安装:
apt install -y g++
真实回显:
WARNING: apt does not have a stable CLI interface. Use with caution in scripts.
Reading package lists...
Building dependency tree...
Reading state information...
g++ is already the newest version (4:11.2.0-1ubuntu1).
g++ set to manually installed.
0 upgraded, 0 newly installed, 0 to remove and 8 not upgraded.
💡 说明:本环境已预先安装 g++,因此回显为「已是最新版本」。全新服务器上首次执行时,apt 会下载并安装 g++、g++-11、gcc-11、cpp-11、libstdc++-11-dev 等一组依赖包,结尾同样显示
Setting up ...的配置过程。
查看 g++ 软件包的候选与安装版本:
apt-cache policy g++
真实回显:
g++:
Installed: 4:11.2.0-1ubuntu1
Candidate: 4:11.2.0-1ubuntu1
Version table:
*** 4:11.2.0-1ubuntu1 500
500 http://archive.ubuntu.com/ubuntu jammy/main amd64 Packages
100 /var/lib/dpkg/status
3.4 验证安装
g++ --version
真实回显:
g++ (Ubuntu 11.4.0-1ubuntu1~22.04.3) 11.4.0
Copyright (C) 2021 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
确认命令所在路径:
which g++
真实回显:
/usr/bin/g++
四、离线安装方案
离线安装适用于目标服务器无法连接互联网的场景:先在可联网的机器上用 apt 下载 .deb 软件包,再拷贝到离线服务器上用 dpkg 安装。
4.1 下载软件包(联网机器)
使用 --download-only 只下载不安装,--no-install-recommends 跳过推荐的额外包:
apt install --download-only --no-install-recommends -y g++
真实回显:
WARNING: apt does not have a stable CLI interface. Use with caution in scripts.
Reading package lists...
Building dependency tree...
Reading state information...
g++ is already the newest version (4:11.2.0-1ubuntu1).
0 upgraded, 0 newly installed, 0 to remove and 8 not upgraded.
⚠️ 注意:当目标包在系统上已安装且为最新版本时,
--download-only不会重复下载任何文件。在未安装 g++ 的联网机器上执行上述命令,apt 会将该包及其全部依赖下载到/var/cache/apt/archives/目录,回显中会出现Downloading ...与Get:1 ... g++ ...等行。
4.2 查看下载缓存目录
查看 apt 缓存目录中已有的 .deb 文件(本机缓存了 g++ 的依赖包):
ls -lh /var/cache/apt/archives/*.deb | head
真实回显:
-rw-r--r-- 1 root root 9.6M Feb 12 2026 /var/cache/apt/archives/cpp-11_11.4.0-1ubuntu1~22.04.3_amd64.deb
-rw-r--r-- 1 root root 20M Feb 12 2026 /var/cache/apt/archives/gcc-11_11.4.0-1ubuntu1~22.04.3_amd64.deb
-rw-r--r-- 1 root root 5.0K Aug 5 2021 /var/cache/apt/archives/gcc_4%3a11.2.0-1ubuntu1_amd64.deb
-rw-r--r-- 1 root root 2.5M Feb 12 2026 /var/cache/apt/archives/libgcc-11-dev_11.4.0-1ubuntu1~22.04.3_amd64.deb
4.3 拷贝到离线目录
mkdir -p /opt/devchain-demo/gxx-ubuntu-test/offline
cp /var/cache/apt/archives/*.deb /opt/devchain-demo/gxx-ubuntu-test/offline/
查看离线目录内容:
ls -lh /opt/devchain-demo/gxx-ubuntu-test/offline/
真实回显:
total 32M
-rw-r--r-- 1 root root 9.6M Oct 6 06:24 cpp-11_11.4.0-1ubuntu1~22.04.3_amd64.deb
-rw-r--r-- 1 root root 20M Oct 6 06:24 gcc-11_11.4.0-1ubuntu1~22.04.3_amd64.deb
-rw-r--r-- 1 root root 5.0K Oct 6 06:24 gcc_4%3a11.2.0-1ubuntu1_amd64.deb
-rw-r--r-- 1 root root 2.5M Oct 6 06:24 libgcc-11-dev_11.4.0-1ubuntu1~22.04.3_amd64.deb
4.4 查看软件包信息
安装前可用 dpkg-deb -I 查看 .deb 包的元信息(包名、版本、依赖等)。以 gcc-11 为例:
dpkg-deb -I /opt/devchain-demo/gxx-ubuntu-test/offline/gcc-11_11.4.0-1ubuntu1~22.04.3_amd64.deb | head -25
真实回显:
new Debian package, version 2.0.
size 20143406 bytes: control archive=1666 bytes.
942 bytes, 16 lines control
2804 bytes, 36 lines md5sums
Package: gcc-11
Version: 11.4.0-1ubuntu1~22.04.3
Architecture: amd64
Maintainer: Ubuntu Core developers <ubuntu-devel-discuss@lists.ubuntu.com>
Installed-Size: 52747
Depends: cpp-11 (= 11.4.0-1ubuntu1~22.04.3), gcc-11-base (= 11.4.0-1ubuntu1~22.04.3), libcc1-0 (>= 11.4.0-1ubuntu1~22.04.3), binutils (>= 2.38), libgcc-11-dev (= 11.4.0-1ubuntu1~22.04.3), libc6 (>= 2.34), libgcc-s1 (>= 3.0), libgmp10 (>= 2:6.2.1+dfsg), libisl23 (>= 0.15), libmpc3 (>= 1.1.0), libmpfr6 (>= 3.1.3), libstdc++6 (>= 5), libzstd1 (>= 1.4.0), zlib1g (>= 1:1.1.4)
Recommends: libc6-dev (>= 2.13-0ubuntu6)
Suggests: gcc-11-multilib, gcc-11-doc (>= 11), gcc-11-locales (>= 11)
Replaces: cpp-11 (<< 7.1.1-8)
Provides: c-compiler
Section: devel
Priority: optional
Homepage: http://gcc.gnu.org/
Description: GNU C compiler
This is the GNU C compiler, a fairly portable optimizing compiler for C.
Original-Maintainer: Debian GCC Maintainers <debian-gcc@lists.debian.org>
4.5 离线安装
在离线服务器上,进入存放 .deb 的目录后执行:
dpkg -i /opt/devchain-demo/gxx-ubuntu-test/offline/*.deb
💡 说明:
dpkg -i不会自动解析依赖。若提示依赖缺失,可先执行apt install -f自动补齐,或使用apt install ./包名.deb(apt 会同时处理本地包与在线依赖)。离线安装后同样用g++ --version验证。
五、命令与参数详解
本章所有示例源码与产物统一放在示例工作目录 /opt/devchain-demo/gxx-ubuntu-test 下。先准备最基础的 C++ 程序 hello.cpp:
#include <iostream>
int main()
{
std::cout << "Hello, Ubuntu 22.04 G++!" << std::endl;
return 0;
}
5.1 版本与基本信息
g++ --version:显示完整版本与版权信息。
g++ --version
真实回显:
g++ (Ubuntu 11.4.0-1ubuntu1~22.04.3) 11.4.0
Copyright (C) 2021 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
g++ -dumpversion:只输出主版本号,适合脚本判断。
g++ -dumpversion
真实回显:
11
g++ -dumpfullversion:输出完整版本号(主.次.修订)。
g++ -dumpfullversion
真实回显:
11.4.0
g++ -dumpmachine:输出目标机器三元组。
g++ -dumpmachine
真实回显:
x86_64-linux-gnu
g++ -v:显示内部配置与编译子过程执行的详细过程,排错时非常有用。
g++ -v 2>&1 | head -20
真实回显:
Using built-in specs.
COLLECT_GCC=g++
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/11/lto-wrapper
OFFLOAD_TARGET_NAMES=nvptx-none:amdgcn-amdhsa
OFFLOAD_TARGET_DEFAULT=1
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 11.4.0-1ubuntu1~22.04.3' --with-bugurl=file:///usr/share/doc/gcc-11/README.Bugs --enable-languages=c,ada,c++,go,brig,d,fortran,objc,obj-c++,m2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-11 --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-plugin --enable-default-pie --with-system-zlib --enable-libphobos-checking=release --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --enable-cet --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none=/build/gcc-11-0odw26/gcc-11-11.4.0/debian/tmp-nvptx/usr,amdgcn-amdhsa=/build/gcc-11-0odw26/gcc-11-11.4.0/debian/tmp-gcn/usr --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu --with-build-config=bootstrap-lto-lean --enable-link-serialization=2
Thread model: posix
Supported LTO compression algorithms: zlib zstd
gcc version 11.4.0 (Ubuntu 11.4.0-1ubuntu1~22.04.3)
g++ --help:查看全部命令行选项(节选)。
g++ --help | sed -n "1,40p"
真实回显:
Usage: g++ [options] file...
Options:
-pass-exit-codes Exit with highest error code from a phase.
--help Display this information.
--target-help Display target specific command line options.
--help={common|optimizers|params|target|warnings|[^]{joined|separate|undocumented}}[,...].
Display specific types of command line options.
(Use '-v --help' to display command line options of sub-processes).
--version Display compiler version information.
-dumpspecs Display all of the built in spec strings.
-dumpversion Display the version of the compiler.
-dumpmachine Display the compiler's target processor.
-print-search-dirs Display the directories in the compiler's search path.
-print-libgcc-file-name Display the name of the compiler's companion library.
-print-file-name=<lib> Display the full path to library <lib>.
-print-prog-name=<prog> Display the full path to compiler component <prog>.
-print-multiarch Display the target's normalized GNU triplet, used as
a component in the library path.
-print-multi-directory Display the root directory for versions of libgcc.
-print-multi-lib Display the mapping between command line options and
multiple library search directories.
-print-multi-os-directory Display the relative path to OS libraries.
-print-sysroot Display the target libraries directory.
-print-sysroot-headers-suffix Display the sysroot suffix used to find headers.
-Wa,<options> Pass comma-separated <options> on to the assembler.
-Wp,<options> Pass comma-separated <options> on to the preprocessor.
-Wl,<options> Pass comma-separated <options> on to the linker.
-Xassembler <arg> Pass <arg> on to the assembler.
-Xpreprocessor <arg> Pass <arg> on to the preprocessor.
-Xlinker <arg> Pass <arg> on to the linker.
-save-temps Do not delete intermediate files.
-save-temps=<arg> Do not delete intermediate files.
-no-canonical-prefixes Do not canonicalize paths when building relative
prefixes to other gcc components.
-pipe Use pipes rather than intermediate files.
-time Time the execution of each subprocess.
-specs=<file> Override built-in specs with the contents of <file>.
-std=<standard> Assume that the input sources are for <standard>.
--sysroot=<directory> Use <directory> as the root directory for headers
and libraries.
g++ -print-search-dirs:显示编译器各子工具与库的搜索路径。
g++ -print-search-dirs
真实回显:
install: /usr/lib/gcc/x86_64-linux-gnu/11/
programs: =/usr/lib/gcc/x86_64-linux-gnu/11/:/usr/lib/gcc/x86_64-linux-gnu/11/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/11/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/11/../../../../x86_64-linux-gnu/bin/x86_64-linux-gnu/11/:/usr/lib/gcc/x86_64-linux-gnu/11/../../../../x86_64-linux-gnu/bin/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/11/../../../../x86_64-linux-gnu/bin/
libraries: =/usr/lib/gcc/x86_64-linux-gnu/11/:/usr/lib/gcc/x86_64-linux-gnu/11/../../../../x86_64-linux-gnu/lib/x86_64-linux-gnu/11/:/usr/lib/gcc/x86_64-linux-gnu/11/../../../../x86_64-linux-gnu/lib/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/11/../../../../x86_64-linux-gnu/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/11/../../../x86_64-linux-gnu/11/:/usr/lib/gcc/x86_64-linux-gnu/11/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/11/../../../../lib/:/lib/x86_64-linux-gnu/11/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/11/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/11/../../../../x86_64-linux-gnu/lib/:/usr/lib/gcc/x86_64-linux-gnu/11/../../../:/lib/:/usr/lib/
g++ -print-file-name=<库>:显示指定库或头文件的完整路径。
g++ -print-file-name=libstdc++.so
g++ -print-file-name=libstdc++.a
真实回显:
/usr/lib/gcc/x86_64-linux-gnu/11/libstdc++.so
/usr/lib/gcc/x86_64-linux-gnu/11/libstdc++.a
5.2 编译四阶段:-E / -S / -c / -o
g++ 将 C++ 源码编译为可执行文件共经历四个阶段,可用参数单独控制每个阶段。
阶段一:预处理(-E),展开 #include、#define 宏,生成 .i 文件:
g++ -E hello.cpp -o hello.i
真实回显(无输出,表示成功):
== E 完成 ==
💡 说明:预处理后 iostream 等大量头文件被展开,hello.i 体积达 778417 字节。查看其开头:
head -3 hello.i
真实回显:
# 0 "hello.cpp"
# 0 "<built-in>"
# 0 "<command-line>"
阶段二:编译(-S),把预处理结果翻译为汇编代码,生成 .s 文件:
g++ -S hello.i -o hello.s
查看汇编代码开头:
head -5 hello.s
真实回显:
.file "hello.cpp"
.text
.local _ZStL8__ioinit
.comm _ZStL8__ioinit,1,1
.section .rodata
💡 说明:
_ZStL8__ioinit是 C++ 名称修饰(name mangling)后的符号,对应 std::ios_base 的初始化对象,这也是 g++ 与 gcc 处理差异的体现之一。
阶段三:汇编(-c),把汇编代码转换为目标文件(机器码),生成 .o 文件:
g++ -c hello.s -o hello.o
阶段四:链接(-o),把目标文件与库链接成可执行文件:
g++ hello.o -o hello
运行:
./hello
真实回显:
Hello, Ubuntu 22.04 G++!
查看各阶段产物大小:
ls -l hello.i hello.s hello.o hello
真实回显:
-rwxr-xr-x 1 root root 16528 Oct 6 06:20 hello
-rw-r--r-- 1 root root 778417 Oct 6 06:20 hello.i
-rw-r--r-- 1 root root 2760 Oct 6 06:20 hello.o
-rw-r--r-- 1 root root 2264 Oct 6 06:20 hello.s
💡 说明:也可以一条命令直接完成四个阶段:
g++ hello.cpp -o hello,中间文件不落盘。
5.3 语言标准选项:-std=c++11 / c++14 / c++17 / c++20
-std= 指定 C++ 语言标准,gcc 11 完整支持 C++11/14/17/20。逐一编译并运行:
g++ -std=c++11 hello.cpp -o h11
g++ -std=c++14 hello.cpp -o h14
g++ -std=c++17 hello.cpp -o h17
g++ -std=c++20 hello.cpp -o h20
编译成功无报错,查看产物:
ls -l h11 h14 h17 h20
真实回显:
-rwxr-xr-x 1 root root 16576 Oct 6 06:21 h11
-rwxr-xr-x 1 root root 16576 Oct 6 06:21 h14
-rwxr-xr-x 1 root root 16528 Oct 6 06:21 h17
-rwxr-xr-x 1 root root 16528 Oct 6 06:21 h20
分别运行验证:
./h11
./h14
./h17
./h20
真实回显(每个输出一致):
Hello, Ubuntu 22.04 G++!
Hello, Ubuntu 22.04 G++!
Hello, Ubuntu 22.04 G++!
Hello, Ubuntu 22.04 G++!
💡 说明:gcc 11 默认标准为
gnu++17(即 C++17 + GNU 扩展)。hello.cpp 仅使用基础语法,因此在 c++11 至 c++20 各标准下均编译通过。
5.4 优化选项:-O0 / -O1 / -O2 / -O3
-O 系列控制编译器优化级别,数值越大优化越激进。逐一编译对比产物大小:
g++ -O0 -o hello_O0 hello.cpp
g++ -O1 -o hello_O1 hello.cpp
g++ -O2 -o hello_O2 hello.cpp
g++ -O3 -o hello_O3 hello.cpp
查看对比:
ls -l hello hello_O0 hello_O1 hello_O2 hello_O3
真实回显:
-rwxr-xr-x 1 root root 16528 Oct 6 06:20 hello
-rwxr-xr-x 1 root root 16528 Oct 6 06:21 hello_O0
-rwxr-xr-x 1 root root 16400 Oct 6 06:21 hello_O1
-rwxr-xr-x 1 root root 16584 Oct 6 06:21 hello_O2
-rwxr-xr-x 1 root root 16560 Oct 6 06:21 hello_O3
💡 说明:
-O0不做优化(调试友好),-O1基本优化,-O2是发布版本常用级别,-O3在 -O2 基础上增加更多循环与内联优化。对于 hello.cpp 这类小程序体积差异不明显,但对真实项目影响显著。
5.5 警告选项:-Wall / -Wextra / -Werror / -Wconversion
准备一个包含「未使用变量」与「double 转 int 隐式转换」问题的 warn.cpp:
#include <iostream>
using namespace std;
int main()
{
int unused_var = 100;
double d = 3.99;
int i = d;
cout << "i = " << i << endl;
return 0;
}
-Wall 开启大部分常用警告,-Wextra 增加额外(可能无用)的警告。编译:
g++ -Wall -Wextra warn.cpp -o warn
真实回显:
warn.cpp: In function 'int main()':
warn.cpp:6:9: warning: unused variable 'unused_var' [-Wunused-variable]
6 | int unused_var = 100;
| ^~~~~~~~~~
exit=0
💡 说明:
-Wall抓到了未使用变量,但double转int的隐式转换不在 -Wall/-Wextra 范围内,需要-Wconversion才能捕获。
-Wconversion:对可能改变值的隐式类型转换给出警告:
g++ -Wconversion warn.cpp -o warn_conv
真实回显:
warn.cpp: In function 'int main()':
warn.cpp:8:13: warning: conversion from 'double' to 'int' may change value [-Wfloat-conversion]
8 | int i = d;
| ^
exit=0
-Werror:把所有警告当作错误,编译直接失败:
g++ -Wall -Wextra -Werror warn.cpp -o warn2
真实回显:
warn.cpp: In function 'int main()':
warn.cpp:6:9: error: unused variable 'unused_var' [-Werror=unused-variable]
6 | int unused_var = 100;
| ^~~~~~~~~~
cc1plus: all warnings being treated as errors
exit=1
⚠️ 注意:
-Werror用于强制代码零警告,CI 流水线中常用。它把 warning 提升为 error,编译退出码变为 1,不生成目标文件。
查看 -Wall 等选项的帮助描述:
g++ --help=warnings | grep -E "^\s+-W(all|extra|error|conversion|unused-variable)\b"
真实回显:
-Wall Enable most warning messages.
-Wconversion Warn for implicit type conversions that may
-Werror-implicit-function-declaration This switch is deprecated; use
-Werror=implicit-function-declaration instead.
-Wextra Print extra (possibly unwanted) warnings.
-Wunused-variable Warn when a variable is unused.
5.6 调试与性能分析:-g / -pg
-g:生成调试信息(DWARF),供 gdb 等调试器使用:
g++ -g hello.cpp -o hello_dbg
对比是否带调试信息的产物大小:
ls -l hello hello_dbg
真实回显:
-rwxr-xr-x 1 root root 16528 Oct 6 06:20 hello
-rwxr-xr-x 1 root root 33216 Oct 6 06:21 hello_dbg
💡 说明:带 -g 的可执行文件体积从 16528 字节增大到 33216 字节,多出的部分即调试符号信息。
-pg:生成 gprof 性能分析所需的调用计数代码:
g++ -pg hello.cpp -o hello_pg
查看产物:
ls -l hello_pg
真实回显:
-rwxr-xr-x 1 root root 16944 Oct 6 06:24 hello_pg
💡 说明:运行
./hello_pg后会在当前目录生成gmon.out,再用gprof hello_pg gmon.out即可查看各函数耗时占比。
5.7 宏定义与预定义宏:-D / -U / -dM
-D<宏>[=<值>]:在命令行定义宏,等价于源码中的 #define。准备 debug.cpp:
#include <iostream>
using namespace std;
int main()
{
#ifdef DEBUG
cout << "DEBUG=" << DEBUG << " is defined" << endl;
#else
cout << "DEBUG is not defined" << endl;
#endif
return 0;
}
带 -DDEBUG=1 编译并运行:
g++ -DDEBUG=1 debug.cpp -o d1
./d1
真实回显:
DEBUG=1 is defined
不带宏编译并运行:
g++ debug.cpp -o d0
./d0
真实回显:
DEBUG is not defined
-U<宏>:取消已定义的宏。先 -D 再 -U,宏最终未定义:
g++ -DDEBUG=1 -UDEBUG debug.cpp -o d2
./d2
真实回显:
DEBUG is not defined
-dM -E:输出全部预定义宏。直接对空输入执行时,g++ 会把无扩展名的 stdin 按 C 语言处理,需用 -x c++ 强制 C++ 语言:
echo "" | g++ -x c++ -dM -E - | grep __cplusplus
真实回显:
#define __cplusplus 201703L
💡 说明:
__cplusplus值 201703L 对应 C++17,与 gcc 11 默认标准 gnu++17 一致(C++11 为 201103L、C++14 为 201402L、C++20 为 202002L)。
对真实源文件同样可以查询:
g++ -dM -E hello.cpp | grep __cplusplus
真实回显:
#define __cplusplus 201703L
5.8 依赖关系生成:-MM / -M
-MM:输出源文件的头文件依赖(仅用户头文件,不含系统头),供 Makefile 使用:
g++ -MM hello.cpp
真实回显:
hello.o: hello.cpp
-M:输出完整依赖,包含全部系统头文件:
g++ -M hello.cpp
真实回显(节选):
hello.o: hello.cpp /usr/include/stdc-predef.h \
/usr/include/c++/11/iostream \
/usr/include/x86_64-linux-gnu/c++/11/bits/c++config.h \
/usr/include/x86_64-linux-gnu/c++/11/bits/os_defines.h \
/usr/include/features.h /usr/include/features-time64.h \
/usr/include/x86_64-linux-gnu/bits/wordsize.h \
/usr/include/x86_64-linux-gnu/bits/timesize.h \
/usr/include/x86_64-linux-gnu/sys/cdefs.h \
/usr/include/x86_64-linux-gnu/bits/long-double.h \
/usr/include/x86_64-linux-gnu/gnu/stubs.h \
/usr/include/x86_64-linux-gnu/gnu/stubs-64.h \
/usr/include/x86_64-linux-gnu/c++/11/bits/cpu_defines.h \
/usr/include/c++/11/pstl/pstl_config.h /usr/include/c++/11/ostream \
/usr/include/c++/11/ios /usr/include/c++/11/iosfwd \
/usr/include/c++/11/bits/stringfwd.h \
...
💡 说明:Makefile 中常把
g++ -MM hello.cpp的输出重定向到.d依赖文件,实现头文件变更后自动重编。
5.9 C++ 特性演示:类、构造函数、成员函数与函数重载
准备 class.cpp,演示类定义、构造函数、成员函数与函数重载:
#include <iostream>
using namespace std;
class Point {
public:
Point(int x = 0, int y = 0) : m_x(x), m_y(y) {}
void move(int dx, int dy) { m_x += dx; m_y += dy; }
int x() const { return m_x; }
int y() const { return m_y; }
private:
int m_x, m_y;
};
// 函数重载
void print(int v) { cout << "int: " << v << endl; }
void print(double v) { cout << "double: " << v << endl; }
void print(const char* s) { cout << "str: " << s << endl; }
int main()
{
Point p(1, 2);
p.move(3, 4);
cout << "Point: (" << p.x() << ", " << p.y() << ")" << endl;
print(42);
print(3.14);
print("hello overload");
return 0;
}
编译并运行:
g++ -o class class.cpp
./class
真实回显:
Point: (4, 6)
int: 42
double: 3.14
str: hello overload
💡 说明:三个
42匹配int版,3.14匹配double版,字符串匹配const char*版。
5.10 模板函数演示
准备 template.cpp,演示函数模板:
#include <iostream>
using namespace std;
template <typename T>
T my_max(T a, T b)
{
return (a > b) ? a : b;
}
int main()
{
cout << "max(3, 7) = " << my_max(3, 7) << endl;
cout << "max(2.5, 1.8) = " << my_max(2.5, 1.8) << endl;
cout << "max('x', 'a') = " << my_max<char>('x', 'a') << endl;
return 0;
}
编译并运行:
g++ -o tmpl template.cpp
./tmpl
真实回显:
max(3, 7) = 7
max(2.5, 1.8) = 2.5
max(x, a) = x
💡 说明:
my_max(3, 7)自动推导 T 为 int,my_max(2.5, 1.8)推导为 double;my_max<char>显式指定 T 为 char,按字符编码 'x'(120) > 'a'(97) 返回 'x'。
5.11 头文件搜索路径:-I
-I<目录>:追加头文件搜索路径。先建立自定义头文件目录:
mkdir -p include
写入 include/mylib.h:
#ifndef MYLIB_H
#define MYLIB_H
int cube(int x);
#endif
uselib.cpp 通过 #include "mylib.h" 引用:
#include <iostream>
#include "mylib.h"
using namespace std;
int cube(int x) { return x * x * x; }
int main()
{
cout << "cube(3) = " << cube(3) << endl;
return 0;
}
用 -I 指定头文件目录并编译运行:
g++ -I include uselib.cpp -o uselib
./uselib
真实回显:
cube(3) = 27
5.12 静态库制作与链接:-c、ar、-L、-l、-static
准备两个库函数 foo.cpp 与调用程序 main.cpp:
#include <iostream>
using namespace std;
int add(int a, int b)
{
return a + b;
}
int multiply(int a, int b)
{
return a * b;
}
#include <iostream>
using namespace std;
int add(int a, int b);
int multiply(int a, int b);
int main()
{
cout << "add(2, 3) = " << add(2, 3) << endl;
cout << "multiply(2, 3) = " << multiply(2, 3) << endl;
return 0;
}
第一步:只编译不链接生成目标文件:
g++ -c foo.cpp -o foo.o
第二步:用 ar 打包静态库:
ar rcs libfoo.a foo.o
ar t:列出归档中的成员:
ar t libfoo.a
真实回显:
foo.o
第三步:-L. 指定库搜索目录,-lfoo 链接 libfoo.a,-static 全静态链接:
g++ main.cpp -L. -lfoo -static -o app_static
运行:
./app_static
真实回显:
add(2, 3) = 5
multiply(2, 3) = 6
查看产物大小:
ls -l app_static
真实回显:
-rwxr-xr-x 1 root root 2404176 Oct 6 06:22 app_static
💡 说明:
-static把所有库(含 libstdc++、libc)静态链接进可执行文件,产物 2.4MB,不依赖运行环境中的动态库,可直接拷到同架构机器运行。
5.13 共享库制作与链接:-shared / -fPIC
-shared:生成共享库;-fPIC:生成位置无关代码(共享库必须):
g++ -shared -fPIC -o libfoo.so foo.cpp
查看产物:
ls -l libfoo.so
真实回显:
-rwxr-xr-x 1 root root 15824 Oct 6 06:22 libfoo.so
链接生成依赖共享库的可执行文件:
g++ main.cpp -L. -lfoo -o app_dyn
⚠️ 注意:运行时动态链接器默认不会搜索当前目录。指定共享库路径运行:
LD_LIBRARY_PATH=. ./app_dyn
真实回显:
add(2, 3) = 5
multiply(2, 3) = 6
用 ldd 查看动态依赖:
ldd app_dyn
真实回显:
linux-vdso.so.1 (0x00007ffde6fc2000)
libfoo.so => not found
libstdc++.so.6 => /lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007e8de8f7b000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007e8de8d52000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007e8de8c6b000)
/lib64/ld-linux-x86-64.so.2 (0x00007e8de91b2000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007e8de8c4b000)
⚠️ 注意:上面未设
LD_LIBRARY_PATH时libfoo.so => not found,这正是必须用LD_LIBRARY_PATH=.或export LD_LIBRARY_PATH=.才能运行的原因;libstdc++.so.6、libc.so.6 等系统库则正常解析。
5.14 gcc 与 g++ 的差异
g++ 是 C++ 驱动:即使输入 C 源文件也能编译链接,且链接阶段会自动带上 libstdc++。准备一个 C 源文件 hello.c:
#include <stdio.h>
int main(void)
{
printf("Hello from C source compiled by g++\n");
return 0;
}
用 g++ 编译链接并运行:
g++ hello.c -o hello_c
./hello_c
真实回显:
Hello from C source compiled by g++
💡 说明:g++ 对
.c文件按 C 语言编译,但链接时仍自动链接 C++ 运行时库,因此即使 C 程序也能用 g++ 完成链接。
验证 g++ 链接的可执行文件确实依赖 libstdc++:
ldd hello | grep stdc
真实回显:
libstdc++.so.6 => /lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007b484d186000)
⚠️ 注意:如果用
gcc编译 C++ 源文件(如gcc hello.cpp -o h),gcc 不会自动链接 libstdc++,会出现undefined reference to 'std::cout'一类链接错误;g++ 则会自动链接,这是两者最核心的差异。
六、配置说明
6.1 环境变量
PATH:/usr/bin/g++已由包管理器写入系统 PATH,无需额外配置。LD_LIBRARY_PATH:运行依赖自建共享库的程序时,需要把库目录加入该变量,例如export LD_LIBRARY_PATH=/opt/devchain-demo/gxx-ubuntu-test:$LD_LIBRARY_PATH。CXX:make/cmake 等构建系统默认取c++或g++作为 C++ 编译器,可用export CXX=g++显式指定。
6.2 默认语言标准
gcc 11 的默认标准是 gnu++17(C++17 + GNU 扩展)。可通过 g++ -std=c++20 等参数切换;也可用环境变量 CXXFLAGS="-std=c++20" 全局指定。
6.3 多版本共存
若系统同时安装多个 gcc 版本(如 g++-10 与 g++-11),可通过 update-alternatives --config g++ 切换默认版本。本机仅安装 11.4.0 一个版本,g++ 直接指向 /usr/bin/g++-11。
七、常见问题(FAQ)
Q1:执行 g++ 提示 command not found?
说明 g++ 未安装。执行 apt update && apt install -y g++,或直接安装元包 build-essential(包含 gcc、g++、make 等整套工具链)。
Q2:编译报 undefined reference to 'std::cout'?
使用了 gcc 而不是 g++ 编译/链接 C++ 程序。改用 g++,或在 gcc 命令后手动追加 -lstdc++。
Q3:编译报 /usr/bin/ld: cannot find -lfoo?
链接时 -lfoo 找不到 libfoo 库。检查是否使用 -L<目录> 指定了库所在路径,或库文件名是否为 libfoo.a / libfoo.so(-lfoo 会自动拼接 lib 前缀)。
Q4:警告一大堆,如何快速清零?
用 -Wall -Wextra -Werror 组合,把警告全部升级为错误,逐个修复到零警告。
Q5:./app_dyn 运行报 error while loading shared libraries: libfoo.so?
共享库目录不在动态链接器搜索路径。执行 export LD_LIBRARY_PATH=.(或库所在目录)后重新运行;生产环境建议把库安装到 /usr/local/lib 并执行 ldconfig。
Q6:hello.i 文件怎么这么大?
-E 预处理把 iostream 等全部头文件展开到源码中,属正常现象;中间文件可用 -save-temps 保留,或编译完成后删除。
Q7:如何查看当前编译器的预定义宏?
执行 g++ -dM -E hello.cpp 即可输出全部预定义宏;无输入文件时需加 -x c++ 强制 C++ 语言,否则会按 C 语言处理导致 __cplusplus 缺失。
八、卸载与清理
8.1 查看已安装状态
dpkg -l 查看 g++ 软件包安装状态(前两列 ii 表示已安装且配置完成):
dpkg -l g++
真实回显:
Desired=Unknown/Install/Remove/Purge/Hold
| Status=Not/Inst/Conf-files/Unpacked/halF-conf/Half-inst/trig-aWait/Trig-pend
|/ Err?=(none)/Reinst-required (Status,Err: uppercase=bad)
||/ Name Version Architecture Description
+++-==============-=================-============-=================================
ii g++ 4:11.2.0-1ubuntu1 amd64 GNU C++ compiler
查看包详情与依赖关系:
apt-cache show g++ | head -15
真实回显:
Package: g++
Architecture: amd64
Version: 4:11.2.0-1ubuntu1
Priority: optional
Section: devel
Source: gcc-defaults (1.193ubuntu1)
Origin: Ubuntu
Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>
Original-Maintainer: Debian GCC Maintainers <debian-gcc@lists.debian.org>
Bugs: https://bugs.launchpad.net/ubuntu/+filebug
Installed-Size: 16
Provides: c++-compiler, g++-x86-64-linux-gnu (= 4:11.2.0-1ubuntu1)
Depends: cpp (= 4:11.2.0-1ubuntu1), gcc (= 4:11.2.0-1ubuntu1), g++-11 (>= 11.2.0-1~), gcc-11 (>= 11.2.0-1~)
Suggests: g++-multilib
Filename: pool/main/g/gcc-defaults/g++_11.2.0-1ubuntu1_amd64.deb
8.2 卸载
移除 g++(保留配置文件):
apt remove -y g++
彻底卸载并删除配置文件:
apt purge -y g++
清理不再需要的依赖包:
apt autoremove -y
8.3 清理软件包缓存
清理 /var/cache/apt/archives/ 下的 .deb 缓存,释放磁盘空间:
apt clean
九、参考链接
- GCC 官方文档(GCC 11 手册):https://gcc.gnu.org/onlinedocs/
- g++ 命令手册:
man g++ - Ubuntu 软件包 g++ 页面:https://packages.ubuntu.com/jammy/g++
- GNU ar 归档工具手册:
man ar - gprof 性能分析手册:
man gprof