信奥崔老师:常用编译命令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++ 的完整手册。
相关推荐
乌萨奇也要立志学C++3 小时前
【洛谷】二叉树专题全解析:概念、存储、遍历与经典真题实战
数据结构·c++·算法
小谢在学习3 小时前
旋转图像
算法
北京地铁1号线4 小时前
机器学习笔试选择题:题组2
人工智能·算法·机器学习
heeheeai4 小时前
决策树,随机森林,boost森林算法
算法·决策树·随机森林·kotlin·boost
(●—●)橘子……5 小时前
记力扣2271.毯子覆盖的最多白色砖块数 练习理解
数据结构·笔记·python·学习·算法·leetcode
Tiny番茄5 小时前
排序算法汇总,堆排序,归并排序,冒泡排序,插入排序
算法·排序算法
汽车仪器仪表相关领域6 小时前
南华 NHXJ-02 汽车悬架检验台:技术特性与实操应用指南
人工智能·算法·汽车·安全性测试·稳定性测试·汽车检测·年检站
m0_726965986 小时前
【算法】小点:List.remove
算法
rhy200605206 小时前
SAM的低秩特性
人工智能·算法·机器学习·语言模型