信奥崔老师:常用编译命令g++的基本使用

12. 1 常用编译命令g++的基本使用

1. 概念介绍

g++GNU Compiler Collection (GCC) 的一部分,是 GNU 项目发布的 C++ 编译器。它是 Linux 系统上最常用、也是事实上的标准 C++ 编译器。即使你使用 IDE(如 Code::Blocks),其背后调用的很可能就是 g++ 命令。

学习直接使用 g++ 命令,可以让你摆脱对 IDE 的依赖,更深入地理解编译过程,并且能够在任何只有命令行的环境(如远程服务器、竞赛评测系统)中工作。

命令行接口 (Command-Line Interface, CLI)终端 (Terminal) 是一个基于文本的界面,用户通过输入命令来与计算机交互。

2. 算法步骤 (操作流程)

  1. 准备源代码 : 使用任意文本编辑器(如 gedit, nano, vim, 或 VS Code)创建一个 C++ 源文件,例如 program.cpp
  2. 打开终端 : 在 Linux 中,通常按 Ctrl + Alt + T 或从应用程序菜单中找到"终端"。
  3. 导航到文件目录 : 使用 cd (Change Directory) 命令进入你保存 program.cpp 的文件夹。例如,如果文件在桌面的 MyCode 文件夹里,命令是 cd ~/Desktop/MyCode
  4. 编译代码:
    • 使用 -o (output) 标志,可以指定生成的可执行文件名为 my_program。这是最推荐的做法。
    • 这会编译 program.cpp 并生成一个名为 a.out 的默认可执行文件。
    • 最简单的命令 : g++ program.cpp
    • 指定输出文件名 : g++ program.cpp -o my_program
  5. 运行程序:
    • 在终端中输入 ./ 加上你的可执行文件名:./my_program
    • ./ 表示"当前目录",告诉系统在当前文件夹下查找并运行这个程序。
  6. 查看结果: 程序的输出会直接显示在终端中。

3. 算法可视化SVG图示

4. 核心特性

  • 命令行驱动: 所有操作通过命令和参数完成,没有图形界面。
  • 高度可配置: 可以通过大量的编译标志(flags)来精确控制编译过程的方方面面。
  • 透明化: 编译的每一步都清晰可见,错误和警告信息会直接打印在终端上。
  • 脚本化: 可以轻松地将编译命令写入脚本(如 Shell 脚本或 Makefile),实现自动化构建。

5. C++代码基础实现

这个 program.cpp 文件是你将要用 g++ 命令编译的对象。

program.cpp

c 复制代码
#include <iostream>
#include <vector>

int main() {
    std::vector<std::string> messages = {"Hello", "from", "the", "command", "line!"};
    
    for (const std::string& msg : messages) {
        std::cout << msg << " ";
    }
    std::cout << std::endl;
    
    return 0;
}

6. 优化策略 (常用编译标志)

g++ 命令后添加标志可以改变其行为。

  • -o <filename> : 指定输出文件的名称。
    • g++ main.cpp -o main
  • -std=<standard> : 指定 C++ 语言标准。竞赛中常用 c++11, c++14, c++17
    • g++ main.cpp -o main -std=c++17
  • -Wall: 显示所有(All)常见的警告(Warning)。强烈推荐始终使用,可以帮助发现潜在问题。
    • g++ -Wall main.cpp -o main
  • -O2: 开启二级优化(Optimization)。这会让编译器尝试优化代码以提高运行速度。在提交竞赛代码时通常会开启此选项。
    • g++ -O2 main.cpp -o main
  • -g: 加入调试信息。如果你想使用 GDB 调试器来调试程序,必须在编译时加上这个标志。
    • g++ -g main.cpp -o main

组合使用 : g++ -std=c++17 -Wall -O2 main.cpp -o main 是一个非常实用和全面的编译命令。

7. 优缺点

优点:

  • 通用性: 在任何有 GCC 的系统上(几乎所有 Linux 和 macOS)都可以使用,是后台评测系统的标准。
  • 轻量高效: 只需一个终端,不占用额外资源。
  • 控制力强: 精确控制编译的每一个细节。
  • 利于理解: 迫使你理解从源代码到可执行文件的完整过程。

缺点:

  • 学习曲线陡峭: 需要记忆命令和参数,对新手不友好。
  • 手动操作 : 对于多文件项目,手动输入编译命令会变得繁琐(通常会用 make 等工具解决)。
  • 集成度低: 编辑、编译、调试是分离的步骤,需要使用不同的工具。

8. 应用场景

  • 信息学竞赛在线评测 (Online Judge, OJ) : 所有 OJ 系统都是在命令行环境下使用 g++ 或类似编译器来编译你的提交代码。
  • 远程服务器开发: 当你通过 SSH 连接到一台远程 Linux 服务器时,通常只有命令行界面。
  • 自动化构建: 编写脚本来自动编译和测试程序。
  • 快速验证 : 对于单个文件的小程序,直接在终端用 g++ 编译比打开一个大型 IDE 更快。

9. 扩展

  • 编译多个源文件 : g++ file1.cpp file2.cpp -o program
  • 链接库 : 使用 -l 标志来链接外部库,例如链接数学库 libm.so: g++ main.cpp -o main -lm
  • makeMakefile : 当项目文件变多时,手动管理编译命令很困难。make 是一个自动化构建工具,它读取名为 Makefile 的配置文件,根据文件的依赖关系和修改时间,智能地决定需要重新编译哪些文件。
  • **GDB (GNU Debugger)****: 学习使用命令行调试器 GDB,它是 g++ -g 编译出的程序的配套调试工具。

10. 5个课后配套练习及C++代码实现答案

每个练习的答案包含 C++ 代码和用于编译运行的命令。

  1. 练习 : 编写一个程序,打印你的学校名称。使用 g++ 将其编译为名为 myschool 的可执行文件并运行。答案 :school.cpp

    c 复制代码
    #include <iostream>
    int main() {
        std::cout << "Peking University" << std::endl;
        return 0;
    }

    命令:

    bash 复制代码
    g++ school.cpp -o myschool
    ./myschool
  2. 练习 : 编写一个程序,读取两个整数并输出它们的差。使用 -std=c++11-Wall 标志进行编译。答案 :diff.cpp

    c 复制代码
    #include <iostream>
    int main() {
        int a, b;
        std::cin >> a >> b;
        std::cout << a - b << std::endl;
        return 0;
    }

    命令:

    ini 复制代码
    g++ -std=c++11 -Wall diff.cpp -o diff
    ./diff 
  3. 练习 : 编写一个程序,其中包含一个未使用的变量。使用 -Wall 标志编译它,并观察终端输出的警告信息。答案 :warning.cpp

    c 复制代码
    #include <iostream>
    int main() {
        int unused_var = 10; // This will trigger a warning
        std::cout << "Check the compiler warning." << std::endl;
        return 0;
    }

    命令与预期输出:

    csharp 复制代码
    g++ -Wall warning.cpp -o warning
    # 终端会显示类似这样的警告:
    # warning.cpp: In function 'int main()':
    # warning.cpp:4:9: warning: unused variable 'unused_var' [-Wunused-variable]
    #      int unused_var = 10;
    #          ^~~~~~~~~~~~
    ./warning
  4. 练习 : 编写一个计算斐波那契数列第 N 项的程序(使用递归,不考虑效率)。使用 -O2 优化标志编译,并与不使用优化的版本比较(虽然对于小 N 可能看不出时间差异,但这是个好习惯)。答案 :fib.cpp

    c 复制代码
    #include <iostream>
    int fibonacci(int n) {
        if (n <= 1) return n;
        return fibonacci(n - 1) + fibonacci(n - 2);
    }
    int main() {
        int n = 10; // Calculate the 10th Fibonacci number
        std::cout << "Fib(" << n << ") = " << fibonacci(n) << std::endl;
        return 0;
    }

    命令:

    bash 复制代码
    # 优化版本
    g++ -O2 fib.cpp -o fib_opt
    ./fib_opt
    
    # 非优化版本
    g++ fib.cpp -o fib_no_opt
    ./fib_no_opt
  5. 练习 : 创建两个文件 main.cpphelper.cpphelper.cpp 中定义一个函数,main.cpp 中调用它。将这两个文件一起编译成一个名为 multi_file_test 的程序。答案 :helper.h (头文件,可选但推荐)

    arduino 复制代码
    #ifndef HELPER_H
    #define HELPER_H
    void print_message();
    #endif

    helper.cpp

    c 复制代码
    #include <iostream>
    #include "helper.h"
    void print_message() {
        std::cout << "This message is from helper.cpp!" << std::endl;
    }

    main.cpp

    arduino 复制代码
    #include "helper.h"
    int main() {
        print_message();
        return 0;
    }

    命令:

    bash 复制代码
    g++ main.cpp helper.cpp -o multi_file_test
    ./multi_file_test

11. 相关网络资源推荐

  • GCC and Make - A Tutorial on how to compile, link and build C/C++ applications
  • g++ command in Linux with examples (GeeksforGeeks)
  • GCC Online Documentation
  • man g++: 在你的 Linux 终端里直接输入这个命令,可以查看 g++ 的完整手册。
相关推荐
Jerry3 小时前
LeetCode 28. 找出字符串中第一个匹配项的下标
算法
Jerry5 小时前
LeetCode 459. 重复的子字符串
算法
海石7 小时前
1500分的题目,确实有实力,不过还是我略胜一筹
算法·leetcode
海石7 小时前
【记忆化搜索】条条大路通AC,走好适合你的那一条,走到后再考虑走得快
算法·leetcode
Jerry9 小时前
LeetCode 151. 反转字符串中的单词
算法
a11177612 小时前
LM 算法迭代过程动画演示(SLAM)
算法
头茬韭菜12 小时前
Context 的生死抉择:四层压缩、截断算法与 Session Memory
算法·ai
Jerry12 小时前
LeetCode 541. 反转字符串 II
算法
Jerry12 小时前
LeetCode 344. 反转字符串
算法
搞科研的小刘选手13 小时前
【香港大学主办&IEEE出版】第六届计算机视觉、应用与算法国际学术会议(CVAA 2026)
算法·计算机视觉·应用·学术会议