乐途乐途
主页
  • 计算机基础

    • TCP/IP
    • Linux
    • HTTP
  • 数据库

    • SQL
    • MySQL 5.7
  • 编程语言

    • C
    • C++
    • Java SE
    • Python2
    • Python3
  • 数据格式

    • JSON
    • XML
  • 认证与安全

    • JWT
  • 工具

    • Markdown
  • Git

    • GitFlow
  • Quartz

    • Quartz
  • Java

    • Maven 入门
    • Maven 进阶
    • MyBatis
    • Spring
    • Spring MVC
  • Java

    • Spring Boot
    • Spring Cloud
    • Spring Cloud Alibaba
    • Spring Security
    • Spring AI
    • Spring Batch
    • Kafka
    • Java 设计模式
  • 缓存

    • Redis
  • 搜索引擎

    • Elasticsearch
  • 分布式协调

    • ZooKeeper
联系
阿里云
主页
  • 计算机基础

    • TCP/IP
    • Linux
    • HTTP
  • 数据库

    • SQL
    • MySQL 5.7
  • 编程语言

    • C
    • C++
    • Java SE
    • Python2
    • Python3
  • 数据格式

    • JSON
    • XML
  • 认证与安全

    • JWT
  • 工具

    • Markdown
  • Git

    • GitFlow
  • Quartz

    • Quartz
  • Java

    • Maven 入门
    • Maven 进阶
    • MyBatis
    • Spring
    • Spring MVC
  • Java

    • Spring Boot
    • Spring Cloud
    • Spring Cloud Alibaba
    • Spring Security
    • Spring AI
    • Spring Batch
    • Kafka
    • Java 设计模式
  • 缓存

    • Redis
  • 搜索引擎

    • Elasticsearch
  • 分布式协调

    • ZooKeeper
联系
阿里云
  • C++ 学习路径
  • 第1章 C++概述与开发环境

    • C++ 语言概述与编译模型
    • 第一个 C++ 程序与规范
    • 开发环境配置
    • 预处理指令详解
  • 第2章 基本语法与类型系统

    • 变量与基本类型
    • 类型转换
    • 枚举类型
    • 引用与指针
    • 数组与 stdarray
    • 字符串与原始字符串字面量
    • const 与 constexpr
    • nullptr 与空指针
    • 类型推导 auto 与 decltype
    • 基于范围的 for 循环
    • 值类别全面解析
    • char16_t 与 char32_t
    • static_assert 编译期断言
  • 第3章 函数与重载

    • 函数声明与定义
    • 函数重载
    • 默认参数与内联函数
    • Lambda 表达式
    • 函数对象与 stdfunction
    • 后置返回类型与 noexcept
  • 第4章 类与对象

    • 类的基本定义
    • 构造函数与析构函数
    • 拷贝控制
    • 移动构造函数与移动赋值
    • 列表初始化与类内初始化器
    • 静态成员与嵌套类
    • 友元
    • =default 与 =delete
  • 第5章 继承与多态

    • 继承基础
    • 虚函数与多态
    • 虚函数表与动态绑定原理
    • 虚析构函数
    • 抽象类与纯虚函数
    • 多重继承与虚继承
    • 继承构造函数
  • 第6章 运算符重载

    • 运算符重载基础
    • 算术与关系运算符重载
    • 赋值与移动运算符重载
    • 特殊运算符重载
  • 第7章 模板与泛型编程

    • 函数模板
    • 类模板
    • 模板特化与偏特化
    • 可变参数模板
    • 别名模板与模板模板参数
    • SFINAE 与类型萃取
    • 依赖名与 typename/template 关键字
  • 第8章 异常处理

    • 异常处理机制
    • noexcept 与异常安全
    • RAII 与异常安全实践
  • 第9章 内存管理与智能指针

    • 动态内存与内存分区
    • RAII 惯用法
    • unique_ptr
    • shared_ptr 与 weak_ptr
    • 内存管理最佳实践
  • 第10章 右值引用与移动语义

    • 右值引用与值类别深度解析
    • std::move 原理与使用
    • 完美转发与 std::forward
    • 移动语义性能对比与最佳实践
  • 第11章 STL容器

    • vector 深度剖析
    • deque 内部机制
    • list 与 forward_list
    • map 与 set 深度解析
    • unordered 容器与哈希原理
    • array 与 tuple
    • 容器适配器
    • 容器选择全景指南
  • 第12章 STL算法与迭代器

    • 迭代器体系全解
    • 非变异算法
    • 变异算法
    • 排序与二分算法
    • Lambda 与算法组合
    • std::random 随机数库
    • 自定义迭代器开发
  • 第13章 IO流与文件

    • 标准 IO 流
    • 格式化输出控制
    • 文件流操作
    • 字符串流
    • std::regex 正则表达式
  • 第14章 并发与多线程

    • thread 基础与线程管理
    • mutex 与 lock_guard
    • unique_lock 与 condition_variable
    • thread_local 线程局部存储
    • atomic 与内存序
    • future 与 async 异步编程
    • std::chrono 时间库
  • 第15章 现代C++新特性

    • 从 C++11 到 C++20 演进路线
    • C++14 关键新特性
    • C++17 关键新特性
    • C++20 核心特性速览
  • 第16章 面试考点与最佳实践

    • C++ 综合最佳实践清单
    • 高频面试题精讲
    • 多线程面试题与实战
    • 内存管理常见陷阱与排查
  • 附录

    • C++ 核心知识点
    • C++ 专业术语

第一个 C++ 程序与规范

定义与作用

每个 C++ 程序都有一个入口函数 main,它是由操作系统调用的起点。C++ 程序结构、命名空间、头文件组织和编码规范共同构成了程序员的"基本功"——它们决定了代码的可读性、可维护性和跨平台兼容性。

核心原理

程序基本结构

头文件与源文件的职责分离

文件类型包含内容作用
.hpp / .h类声明、函数声明、宏定义、模板接口定义,供多翻译单元共享
.cpp函数实现、全局变量定义、main实现细节,只编译一次

命名空间(namespace)

命名空间是 C++ 解决名称冲突的机制。标准库的所有标识符位于 std 命名空间中。

// 三种使用方式
#include <iostream>

// 方式 1: 完全限定名(推荐在头文件中使用)
std::cout << "Hello";

// 方式 2: using 声明(推荐在 .cpp 的函数作用域内使用)
using std::cout;

// 方式 3: using 指令(谨慎使用,绝不放在头文件全局作用域)
using namespace std;

main 函数的合法签名

int main() { }                              // 标准形式
int main(int argc, char* argv[]) { }        // 带命令行参数
int main(int argc, char** argv) { }         // 等价形式
auto main() -> int { }                      // C++11 后置返回类型

main 函数可以省略 return 语句,编译器自动插入 return 0;(C++ 标准规定)。

完整示例

示例一:学生成绩录入系统

场景说明:一个命令行程序,读取学生姓名和成绩,计算并输出汇总信息。演示基本程序结构、命名空间使用、头文件包含。

grade.hpp

#ifndef GRADE_HPP
#define GRADE_HPP

#include <string>
#include <vector>

namespace sdu {   // 自定义命名空间,避免名称冲突

struct Student {
    std::string name;
    double score;
};

std::vector<Student> input_students();
void print_summary(const std::vector<Student>& students);

}  // namespace sdu

#endif

grade.cpp

#include "grade.hpp"
#include <iostream>
#include <iomanip>

namespace sdu {

std::vector<Student> input_students() {
    std::vector<Student> result;
    int count;

    std::cout << "请输入学生人数: ";
    std::cin >> count;

    for (int i = 0; i < count; ++i) {
        Student s;
        std::cout << "第 " << (i + 1) << " 位学生姓名: ";
        std::cin >> s.name;
        std::cout << "成绩: ";
        std::cin >> s.score;
        result.push_back(s);
    }

    return result;
}

void print_summary(const std::vector<Student>& students) {
    if (students.empty()) {
        std::cout << "无学生数据" << std::endl;
        return;
    }

    double total = 0.0;
    double max_score = students[0].score;
    double min_score = students[0].score;

    for (const auto& s : students) {
        total += s.score;
        if (s.score > max_score) max_score = s.score;
        if (s.score < min_score) min_score = s.score;
    }

    double average = total / students.size();

    std::cout << "\n===== 成绩汇总 =====" << std::endl;
    std::cout << "学生人数: " << students.size() << std::endl;
    std::cout << std::fixed << std::setprecision(2);
    std::cout << "平均分: " << average << std::endl;
    std::cout << "最高分: " << max_score << std::endl;
    std::cout << "最低分: " << min_score << std::endl;
}

}  // namespace sdu

main.cpp

#include "grade.hpp"
#include <iostream>

int main() {
    std::cout << "学生成绩管理系统 v1.0" << std::endl;
    std::cout << "===================" << std::endl;

    auto students = sdu::input_students();
    sdu::print_summary(students);

    return 0;
}

编译命令:

g++ -std=c++11 -Wall -Wextra grade.cpp main.cpp -o grade_system

预期交互示例:

学生成绩管理系统 v1.0
===================
请输入学生人数: 3
第 1 位学生姓名: 张三
成绩: 88
第 2 位学生姓名: 李四
成绩: 95
第 3 位学生姓名: 王五
成绩: 72

===== 成绩汇总 =====
学生人数: 3
平均分: 85.00
最高分: 95.00
最低分: 72.00

逐段分析:

  • namespace sdu 将自定义类型和函数隔离在独立命名空间中,避免与标准库或第三方库冲突
  • 头文件使用 #ifndef/#define/#endif 包含守卫,防止重复包含
  • main 函数中通过 sdu:: 前缀调用自定义命名空间的函数
  • const auto& 在 print_summary 中避免不必要的拷贝
  • 类型 Student 声明为 struct(默认 public),适合纯数据聚合

示例二:预定义宏与跨平台编译

场景说明:编写一个能检测编译器、平台和 C++ 标准版本的程序,演示预定义宏的用法。

env_info.cpp

#include <iostream>
#include <string>

std::string compiler_name() {
#if defined(__clang__)
    return "Clang " + std::to_string(__clang_major__) + "." 
           + std::to_string(__clang_minor__);
#elif defined(__GNUC__)
    return "GCC " + std::to_string(__GNUC__) + "." 
           + std::to_string(__GNUC_MINOR__);
#elif defined(_MSC_VER)
    return "MSVC " + std::to_string(_MSC_VER);
#else
    return "Unknown Compiler";
#endif
}

std::string platform_name() {
#if defined(_WIN32) || defined(_WIN64)
    return "Windows";
#elif defined(__linux__)
    return "Linux";
#elif defined(__APPLE__)
    return "macOS";
#else
    return "Unknown Platform";
#endif
}

std::string cpp_standard() {
#if __cplusplus >= 202002L
    return "C++20 或更新";
#elif __cplusplus >= 201703L
    return "C++17";
#elif __cplusplus >= 201402L
    return "C++14";
#elif __cplusplus >= 201103L
    return "C++11";
#else
    return "C++98/03";
#endif
}

int main() {
    std::cout << "===== 编译环境信息 =====" << std::endl;
    std::cout << "编译器: " << compiler_name() << std::endl;
    std::cout << "平台:   " << platform_name() << std::endl;
    std::cout << "标准:   " << cpp_standard() << std::endl;

    std::cout << "\n===== 文件信息 =====" << std::endl;
    std::cout << "源文件: " << __FILE__ << std::endl;
    std::cout << "行号:   " << __LINE__ << std::endl;
    std::cout << "日期:   " << __DATE__ << std::endl;
    std::cout << "时间:   " << __TIME__ << std::endl;

    return 0;
}

编译命令:

g++ -std=c++17 env_info.cpp -o env_info

预期输出(GCC + Linux 环境示例):

===== 编译环境信息 =====
编译器: GCC 11.4
平台:   Linux
标准:   C++17

===== 文件信息 =====
源文件: env_info.cpp
行号:   50
日期:   Jun 13 2026
时间:   14:30:22

逐段分析:

  • __cplusplus 是 C++ 标准预定义宏,值对应标准版本号(C++11 = 201103L、C++17 = 201703L)
  • 条件编译 #if defined(...) 根据编译器宏选择不同代码路径,实现跨平台兼容
  • __FILE__、__LINE__ 常用于调试日志输出
  • __DATE__ 和 __TIME__ 记录编译时间,用于版本追踪

易错场景与面试考点

易错场景

场景错误表现正确做法
在头文件全局作用域写 using namespace std;污染所有包含该头文件的翻译单元的命名空间头文件中始终使用 std:: 完全限定名
main 函数返回 void某些编译器报错或警告main 必须返回 int
头文件缺少包含守卫redefinition of 'class Foo'始终添加 #ifndef/#define/#endif
自定义命名空间与 std 冲突命名歧义使用项目专属前缀如 ns_projectname
在 .cpp 中直接写函数体而忘记 include 对应头文件另一个 .cpp 找不到声明保持头文件声明 + 源文件实现模式

常见面试问题

  1. main 函数的合法签名有哪些?可以返回 void 吗?——标准规定 main 必须返回 int。void main() 不符合标准,某些编译器可能拒绝。

  2. #include <header> 和 #include "header" 的区别?——尖括号在系统/编译器头文件搜索路径中查找,双引号先在本文件所在目录查找,再按尖括号的方式查找。

  3. 为什么要避免在头文件中使用 using namespace std;?——头文件会被多个翻译单元包含,using 指令将其命名空间导入作用域,导致潜在的名称冲突,且难以追踪。

  4. namespace 与 class 中的 static 函数有何区别?——命名空间用于逻辑分组、避免名称冲突,是开放的可跨文件扩展;类中的 static 函数属于类作用域,具有封装和访问控制。

  5. 如何在一个项目中组织自定义命名空间?——通常以项目名或模块名作为命名空间,如 namespace myproject::network,C++17 起支持嵌套命名空间简写。

小结

  • main 函数是程序入口,必须返回 int
  • 头文件负责声明,源文件负责实现,用包含守卫保护头文件
  • 使用 namespace 隔离标识符,头文件中永远不用 using namespace std;
  • __cplusplus、__FILE__、__LINE__ 等预定义宏用于诊断和跨平台兼容
上一页
C++ 语言概述与编译模型
下一页
开发环境配置