Featured image of post C++ 入门与 vim 开发环境搭建

C++ 入门与 vim 开发环境搭建

从零开始配置 vim 编写 C++:语法高亮、自动补全、编译调试、Makefile 与 CMake 工程化

前置知识

  • Linux/macOS 终端基础(cdlsgrep、管道)
  • 至少熟悉一种编程语言(Java/Python/Go 均可)
  • 知道 gcc / g++ 是什么

为什么选 vim 写 C++

C++ 是少有的"几十年没退出主流"的语言——从 1985 年 Bjarne Stroustrup 发布第一个商用版本,到 2011 年的 C++11、2014 年的 C++14、2017 年的 C++17,模板元、RAII、移动语义、concept(20 概念)层层叠加,IDE 也跟着膨胀:Visual Studio 安装动辄 10GB+,CLion 启动慢、内存吃紧,Eclipse CDT 配置繁琐。

在很多 Linux 老兵眼里,vim + 一组插件就是写 C++ 的"瑞士军刀"——启动快、键盘流不离开主键区、ctags / cscope 跳转精准、配合 gdb 调试毫不输图形 IDE。2010 年代之前,Linux 内核、Hadoop、Chrome 等大型 C++ 项目的核心开发者都靠 vim 写代码。

但这条路有三个关键节点必须打通:语法高亮 → 编译环境 → 调试工具链 → 自动化构建。任何一个断了,体验就掉一档。

一、vim 基础:C++ 语法与缩进

1.1 系统自带的语法文件

1
2
# 多数 Linux 发行版已经自带
ls /usr/share/vim/vim*/syntax/cpp.vim

打开 ~/.vimrc,加一行让 vim 识别 .h .hpp .cc .cpp .cxx

1
2
3
4
" C/C++ 文件类型识别
au BufRead,BufNewFile *.h,*.hpp,*.cc,*.cpp,*.cxx set filetype=cpp
syntax on
filetype indent on

效果:class template namespace auto 关键字高亮,注释块折叠,多行字符串着色。

1.2 缩进策略

C++ 缩进的核心矛盾是 public: / private: 该不该比 class 缩进一格、K&R 还是 Allman 花括号风格。vim 自带的 cpp 缩进文件已经能 cover 80%:

1
2
3
4
5
6
7
8
" 缩进宽度 4 空格、tab 转空格
set tabstop=4
set shiftwidth=4
set expandtab
set autoindent
" C/C++ 缩进风格
set cindent
set cinoptions=:0,g0,t0,(0

:0public: 不缩进、g0 让 C 风格作用域内成员缩进、t0 让函数返回值类型不强制换行——配合 :set cinoptions+=L1 还可以让 case 不缩进。

二、编译工具链:gcc / g++ / clang

2.1 gcc 与 g++ 的区别

gcc 是 GNU C Compiler,g++ 是 GNU C++ Compiler——后者的本质是 gcc -xc++ -lstdc++ -shared-libgccC++ 项目一律用 g++,混用 gcc 会在链接 stdc++ 时报一堆 undefined reference

1
2
3
# 验证版本(C++17 已经是 2017 标准,g++ 7+ 完整支持)
g++ --version
# g++ (Ubuntu 9.4.0-1ubuntu1~20.04.2) 9.4.0

2.2 经典编译命令

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# 单文件
g++ -std=c++17 -Wall -Wextra -O2 -o hello hello.cpp

# 多文件
g++ -std=c++17 -Wall -O2 main.cpp foo.cpp bar.cpp -o myapp

# 分两步:先 -c 生成 .o,再链接
g++ -std=c++17 -Wall -O2 -c main.cpp -o main.o
g++ -std=c++17 -Wall -O2 -c foo.cpp -o foo.o
g++ main.o foo.o -o myapp

-Wall -Wextra 开启几乎所有警告——零警告是 C++ 老兵的第一铁律。

2.3 clang 替代

macOS 默认编译器就是 clang++,Linux 上也能装——编译错误信息比 gcc 友好、静态分析更强:

1
2
3
4
# Ubuntu 安装
sudo apt install clang
clang++ --version
# clang version 10.0.0

很多大项目(Chrome、LLVM 本身)默认用 clang++,编译器版本切换可以用 update-alternatives

1
2
sudo update-alternatives --config c++
# 出现菜单:g++ / clang++ 选其一

三、调试:gdb 基础

3.1 编译时开调试

1
2
3
g++ -std=c++17 -Wall -g -O0 -o debug_demo demo.cpp
# -g  生成调试信息(GNU debug 格式:DWARF)
# -O0 关闭优化,gdb 单步能看到每行

生产构建用 -O2、调试构建用 -O0 -g——-O2 会让变量被寄存器化、循环被展开,单步断点跳得很乱。

3.2 gdb 常用命令

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
gdb ./debug_demo

(gdb) break main              # 在 main 打断点
(gdb) run                     # 启动
(gdb) next                    # 单步(不进入函数)
(gdb) step                    # 单步(进入函数)
(gdb) print var               # 打印变量
(gdb) info locals             # 打印所有局部变量
(gdb) backtrace               # 函数调用栈
(gdb) continue                # 继续执行
(gdb) quit

3.3 段错误定位

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# core dump 开启
ulimit -c unlimited
echo "/tmp/core.%e.%p" | sudo tee /proc/sys/kernel/core_pattern

# 编译
g++ -g -o bug bug.cpp
./bug
# Segmentation fault (core dumped)

gdb ./bug /tmp/core.bug.12345
(gdb) backtrace

vim + gdb 联动:装 clewnvimgdb,可以在 vim 里直接 F8 调出 gdb 控制台、跳转到对应行。

四、Makefile:从源码到产物

g++ 命令一多就乱——头文件改一个,整个项目得全部重编。make 是 C/C++ 项目最朴素的构建系统。

4.1 一个 Makefile 模板

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# 编译器
CXX      = g++
CXXFLAGS = -std=c++17 -Wall -Wextra -O2 -g
LDFLAGS  =

# 源文件、目标文件
SRCS = $(wildcard src/*.cpp)
OBJS = $(SRCS:.cpp=.o)
TARGET = bin/myapp

# 默认目标
all: $(TARGET)

$(TARGET): $(OBJS)
	@mkdir -p bin
	$(CXX) $(OBJS) -o $@ $(LDFLAGS)

%.o: %.cpp
	$(CXX) $(CXXFLAGS) -c $< -o $@

# 头文件依赖
deps:
	$(CXX) -MMD -MP $(CXXFLAGS) $(SRCS) > /dev/null

# 包含自动生成的 .d 文件
-include $(OBJS:.o=.d)

clean:
	rm -f src/*.o src/*.d
	rm -rf bin

.PHONY: all clean deps

关键技巧:

  • wildcard src/*.cpp 自动收集源文件,新增文件不用改 Makefile
  • %.o: %.cpp 模式规则,每个 .cpp 对应一个 .o
  • -MMD -MP 自动追踪头文件依赖:改 foo.h 自动重编 bar.cpp
  • bin/ 目录 @mkdir -p 懒创建

4.2 并行编译

1
2
make -j$(nproc)      # Linux
make -j$(sysctl -n hw.ncpu)  # macOS

多核 CPU 能让构建时间从分钟级压到秒级。

五、CMake:跨平台构建

make 写多了会失控——一个项目几百个源文件、不同平台编译器不同、依赖第三方库路径各异。CMake 是事实标准:写一份 CMakeLists.txt,生成 Makefile / Ninja / Xcode / Visual Studio 工程。

5.1 最简单的 CMakeLists

1
2
3
4
5
6
7
cmake_minimum_required(VERSION 3.10)
project(myapp CXX)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

add_executable(myapp main.cpp foo.cpp bar.cpp)
1
2
3
mkdir build && cd build
cmake ..           # 生成 Makefile
make -j$(nproc)    # 编译

5.2 找第三方库

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
find_package(Boost REQUIRED COMPONENTS filesystem system)
find_package(OpenCV REQUIRED)
find_package(PkgConfig REQUIRED)
pkg_check_modules(SQLITE3 REQUIRED sqlite3)

add_executable(myapp main.cpp)
target_include_directories(myapp PRIVATE ${Boost_INCLUDE_DIRS})
target_link_libraries(myapp
    PRIVATE
    Boost::filesystem
    Boost::system
    ${OpenCV_LIBS}
    ${SQLITE3_LIBRARIES}
)

5.3 现代化 CMake(3.5+ 推荐)

老派 CMake 用全局 include_directories / link_libraries 会污染所有 target,新写法是 target_* + PRIVATE/PUBLIC/INTERFACE 限定作用域:

1
2
3
4
5
6
add_library(mylib STATIC src/foo.cpp)
target_include_directories(mylib PUBLIC include)
target_compile_features(mylib PUBLIC cxx_std_17)

add_executable(myapp main.cpp)
target_link_libraries(myapp PRIVATE mylib)

六、常见坑

现象解法
undefined reference to std::cout用了 gcc 编译 .cpp改用 g++
模板类找不到linker 报缺失符号把模板实现放 .hpp(同文件),或显式实例化
multiple definition of ...头文件有非 inline 函数/变量函数加 inline、变量加 inline(C++17)或 extern
段错误数组越界 / 空指针 / 栈溢出gdb + valgrind --tool=memcheck ./myapp
编译极慢单个翻译单元 1 万+ 行#include 拆分、前向声明、Pimpl 模式
链接 .so 报 cannot find -lxxx库不在标准路径-L/path/to/lib -lxxxLD_LIBRARY_PATH

七、下一步

  • 工具链进阶clangd + clang-tidy 静态分析、include-what-you-use 删无用头文件
  • 构建系统Ninjamake 增量构建快 30%+,cmake -G Ninja ..
  • 包管理vcpkg(微软)、Conan(C++ 生态最主流)安装第三方库
  • 测试GoogleTest(gtest)+ gcovr 看覆盖率
  • 现代 C++:C++20 的 concept / coroutine / module,C++23 的 expected / flat_map

参考资料


2024+ 视角:C++20 / 23 / 26 与现代工具链

C++ 标准演进(2024 视角)

标准发布时间状态编译器支持(2024)
C++172017主流GCC 7+ / Clang 5+ / MSVC 19.14+
C++202020生产可用GCC 10+ / Clang 13+ / MSVC 19.28+
C++232024-02新晋主流GCC 12+ / Clang 16+ / MSVC 19.34+
C++262026(计划)起草中实验分支

C++20 必学特性

  • Concepts:模板约束,写法 template<std::integral T>
  • Modulesimport std;):告别头文件包含地狱——大型项目编译时间降 50%+
  • Coroutinesco_await / co_return):异步代码同步写法
  • Ranges<ranges>):管道式数据处理 nums \| std::views::filter([](int x){ return x%2==0; })
  • std::span:非拥有式数组视图,零拷贝传递
  • std::format:类型安全的字符串格式化(Python f-string 风格)
1
2
3
4
5
6
7
8
9
// C++20 concept 示例
#include <concepts>

template<std::integral T>
T add(T a, T b) { return a + b; }

// 使用
int x = add(1, 2);        // OK
// double y = add(1.0, 2.0);  // 编译错误:double 不是 integral

C++23 必学特性

  • std::expected<T, E>:替代异常或错误码的"成功或失败"类型
  • std::flat_map / std::flat_set:基于连续内存的 map/set——缓存友好,比红黑树快 2-3 倍
  • std::mdspan:多维数组视图——机器学习 / 图像处理天然支持
  • std::print / std::println:类型安全的 print 替代 std::cout <<
  • deducing this(显式对象形参):CRTP 不再需要复杂模板
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
// C++23 std::expected
#include <expected>
#include <string>

std::expected<int, std::string> parseInt(std::string_view s) {
    try {
        return std::stoi(std::string(s));
    } catch (...) {
        return std::unexpected("parse failed: " + std::string(s));
    }
}

auto result = parseInt("42");
if (result) {
    std::println("got: {}", *result);
} else {
    std::println("error: {}", result.error());
}

C++26 路线图(草案)

  • Reflection(静态反射):编译器生成枚举字符串、字段列表
  • Contracts(契约):[[expects: x > 0]] / [[ensures: result > 0]]
  • std::execution(P2300):标准化的异步执行器,senders/receivers
  • Pattern Matchinginspect):函数式语言风格的模式匹配

编译工具链的 2024+ 演进

GCC 14 / Clang 18 / MSVC 19.40+

  • GCC 14:完整 C++23 支持
  • Clang 18:默认 C++17,可选 C++20/23
  • MSVC:与 LLVM 社区代码同步,差异越来越小

跨平台推荐

1
2
3
4
5
6
7
# Ubuntu 24.04 LTS 默认装 GCC 13
sudo apt install g++-14  # 装 GCC 14

# macOS
brew install llvm@18    # 装 Clang 18

# Windows:MSYS2 / vcpkg / WSL2

构建系统的 2024+ 现状

工具状态2024+ 推荐
CMake 3.28+主流首选(Presets 3.27+ 增强)
Ninja 1.12+主流比 Make 快 30%+,CMake -G Ninja
Bazel 7.xGoogle 系 / 跨语言大型项目 + 远程缓存
Meson 1.5+Python 写简单 / 中型项目
xmakeLua 写国内友好(tboox 维护)
Make老派维护遗留项目
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
# CMakePresets.json(2024+ 标准做法)
{
    "version": 6,
    "configurePresets": [
        {
            "name": "base",
            "generator": "Ninja",
            "binaryDir": "${sourceDir}/build/${presetName}",
            "cacheVariables": {
                "CMAKE_CXX_STANDARD": "23",
                "CMAKE_EXPORT_COMPILE_COMMANDS": "ON"
            }
        },
        {
            "name": "debug",
            "inherits": "base",
            "cacheVariables": {
                "CMAKE_BUILD_TYPE": "Debug"
            }
        }
    ]
}
1
2
3
# 一行配置
cmake --preset debug
cmake --build build/debug

包管理的 2024+ 现状

工具特点2024+
vcpkg(微软)3000+ 包,跨平台生产首选
Conan 2.xC++ 生态最成熟复杂项目 + 二进制分发
SpackHPC / 科研学术 / 超级计算
CPM.cmakeCMake 内置简单项目(FetchContent 替代)
xrepo(xmake 系)跨平台国内项目
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# vcpkg 集成(2024+)
# vcpkg.json
{
    "name": "my-project",
    "version-string": "1.0.0",
    "dependencies": [
        "fmt", "spdlog", "boost-system", "boost-filesystem",
        { "name": "qt", "features": ["webengine"] }
    ]
}

调试工具的 2024+ 现状

  • gdb 14+:原生支持 C++20 coroutine 调试
  • lldb 18+:Clang 配套,符号信息更准
  • rr(Mozilla 录制回放):5.x 稳定——重现 bug 一把好手
  • AddressSanitizer / UBSan / ThreadSanitizer:编译器内置,2024+ 必开
  • Valgrind 3.23+:老牌但仍可用
  • Visual Studio Code + CodeLLDB:调试 C++ 的"轻量 IDE"

IDE 的 2024+ 推荐

  • CLion 2024.2+:JetBrains 系,对 CMake / vcpkg 集成最好(付费
  • Visual Studio 2022 17.10+:Windows + C++23 支持最完整
  • VS Code + CMake Tools + clangd免费 + 轻量,Linux/macOS 首选
  • Qt Creator 13+:跨平台 + Qt 项目专用
  • Zed:2024 出现的新编辑器,Rust 写的,启动极快

2024+ 静态分析工具链

工具用途2024+
clang-tidy 18+风格 + bug 模式必装
cppcheck基础静态分析CI 必跑
include-what-you-use检查无用 #include大型项目用
SonarQube 10+企业级代码质量平台中大型
PVS-Studio商业深度分析金融 / 嵌入式

2024+ 推荐组合(跨平台 C++ 项目)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
现代 C++ 项目(C++20/23)
├── 编译器:GCC 14 / Clang 18 / MSVC 19.40
├── 标准:C++20(生产)/ C++23(新项目)
├── 构建:CMake 3.28 + Ninja 1.12 + CMakePresets
├── 包管理:vcpkg(首选)/ Conan 2.x
├── 测试:GoogleTest + gcovr / LLVM-cov
├── 静态分析:clang-tidy + cppcheck
├── 格式化:clang-format 18
├── 调试:gdb 14 / lldb 18 + rr
├── IDE:VS Code + clangd / CLion
├── 编译选项:-Wall -Wextra -Wpedantic -fsanitize=address,undefined
└── CI:GitHub Actions / GitLab CI
使用 Hugo 构建
主题 StackJimmy 设计