前置知识: C

C++ 类型系统

4 minIntermediate

C++ 基本类型、类型推导、类型转换与类型安全。

1. 常量 (Constants)

1.1 const 常量

 // 全局常量
 const int MAX_VALUE = 100;
 int main() {
  // 局部常量
  const double PI = 3.14159;
  // 常量指针
  const int* p = &MAX_VALUE;
  // *p = 200; // 错误:不能修改 const 指针指向的值
  // 指针常量
  int x = 10;
  int* const q = &x;
  *q = 20; // 可以修改指针指向的值
  // q = &MAX_VALUE; // 错误:不能修改指针本身
  // const 引用
  const int& ref = x;
  // ref = 30; // 错误:不能修改 const 引用
  return 0;
 }

1.2 constexpr 常量 (C++11)

 // 编译期常量
 constexpr int factorial(int n) {
  return n <= 1 ? 1 : n * factorial(n - 1);
 }
 int main() {
  constexpr int fact5 = factorial(5); // 编译期计算
  std::cout << "5! = " << fact5 << std::endl;
  return 0;
 }

2. 类型推导

2.1 auto 类型推导 (C++11)

 #include <iostream>
 #include <vector>
 int main() {
  // 基本类型推导
  auto i = 10; // int
  auto d = 3.14; // double
  auto s = "Hello"; // const char*
  auto b = true; // bool
  // 容器类型推导
  std::vector<int> v = {1, 2, 3};
  auto it = v.begin(); // 迭代器类型
  // 函数返回类型推导
  auto add = [](int a, int b) { return a + b; }; // lambda 表达式
  std::cout << "add(5, 3) = " << add(5, 3) << std::endl;
  return 0;
 }

2.2 decltype 类型推导 (C++11)

 #include <iostream>
 int main() {
  int x = 10;
  decltype(x) y = 20; // y 的类型是 int
  double z = 3.14;
  decltype(x + z) w = x + z; // w 的类型是 double
  std::cout << "y = " << y << ", w = " << w << std::endl;
  return 0;
 }

3. 类型别名

3.1 typedef

 #include <iostream>
 // 类型别名
 typedef unsigned int uint;
 typedef std::vector<int> IntVector;
 int main() {
  uint x = 100;
  IntVector v = {1, 2, 3};
  std::cout << "x = " << x << std::endl;
  for (auto num : v) {
  std::cout << num << " ";
  }
  std::cout << std::endl;
  return 0;
 }

3.2 using 别名 (C++11)

 #include <iostream>
 #include <vector>
 // 使用 using 定义类型别名
 using uint = unsigned int;
 using IntVector = std::vector<int>;
 int main() {
  uint x = 100;
  IntVector v = {1, 2, 3};
  std::cout << "x = " << x << std::endl;
  for (auto num : v) {
  std::cout << num << " ";
  }
  std::cout << std::endl;
  return 0;
 }

4. 最佳实践

4.1 代码风格

4.1.1 命名规范

  • 变量和函数camelCasesnake_case
  • 示例:int studentCount;int student_count;
  • 示例:void calculateTotal();void calculate_total();
  • 类和结构体PascalCase
  • 示例:class StudentRecord;
  • 示例:struct Point3D;
  • 常量UPPER_CASE
  • 示例:const int MAX_SIZE = 100;
  • 示例:constexpr double PI = 3.14159;
  • 命名空间lowercase
  • 示例:namespace utils;
  • 示例:namespace math_helpers;
  • 类型别名PascalCasecamelCase
  • 示例:using IntVector = std::vector<int>;
  • 示例:typedef std::map<std::string, int> StringIntMap;

4.1.2 缩进和格式

  • 缩进:使用 4 个空格或 1 个制表符
  • 大括号:使用 K&R 风格(左大括号在同一行)
 if (condition) {
 // 代码
 }
  • 行长度:每行不超过 80-100 个字符
  • 空行:适当使用空行分隔代码块
  • 空格:在操作符前后、逗号后添加空格
 int result = a + b;
 func(a, b, c);

4.1.3 注释

  • 文档注释:函数前添加文档注释
 /**
 * @brief 计算两个数的和
 * @param a 第一个数
 * @param b 第二个数
 * @return 两数之和
 */
 int add(int a, int b) {
 return a + b;
 }
  • 代码注释:为复杂代码添加注释
 // 使用二分查找算法
 int binary_search(const std::vector<int>& arr, int target) {
 // 初始化左右边界
 int left = 0, right = arr.size() - 1;
 // 循环查找
 while (left <= right) {
 int mid = left + (right - left) / 2; // 避免整数溢出
 if (arr[mid] == target) {
 return mid;
 } else if (arr[mid] < target) {
 left = mid + 1;
 } else {
 right = mid - 1;
 }
 }
 return -1;
 }

4.2 型使用建议

4.2.1 基本

  • 优先使用 auto:简化代码,提高可维护性
 auto result = calculate(); // 自动推导返回类型
 auto it = container.begin(); // 简化迭代器类型
  • 使用 constexpr:对于编译期常量,提高性能
 constexpr int MAX_SIZE = 100; // 编译期常量
 constexpr int factorial(int n) { return n <= 1 ? 1 : n * factorial(n-1); }
  • 合理使用 const:提高代码安全性和可读性
 const int& get_value() const; // 常量成员函数,不修改对象状态
 void process(const std::string& str); // 避免复制,且不修改参数
  • 注意类型转换:避免隐式型转换导致的问题
 // 显式转换
 double d = 3.14;
 int i = static_cast<int>(d); // 明确转换意图

4.2.2 复合

  • 使用 STL 容器:优先使用标准库容器
 std::vector<int> numbers; // 动态数组
 std::map<std::string, int> scores; // 键值对
 std::unordered_set<int> unique_values; // 哈希集合
  • 智能指针:使用智能指针管理内存
 std::unique_ptr<MyClass> ptr = std::make_unique<MyClass>();
 std::shared_ptr<MyClass> shared_ptr = std::make_shared<MyClass>();
  • 引用传递:对于大对象,使用引用传递避免复制
 void process_large_object(const LargeObject& obj); // 常量引用

4.3 控制流建议

  • 避免使用 goto:使用结构化控制流
  • 使用范围 for 循环:简化容器遍历
 for (const auto& item : container) {
 // 处理 item
 }
  • 合理使用 switch:对于多分支条件
  • 异常处理:使用 try-catch 处理异常

4.4 输入输出建议

  • 使用 std::cout 和 std::cin:标准库提供的输入输出功能
  • 格式化输出:使用 iomanip 库进行格式化
 std::cout << std::fixed << std::setprecision(2) << value << std::endl;
  • 错误处理:检查输入是否成功
 if (!(std::cin >> value)) {
 std::cerr << "Invalid input" << std::endl;
 std::cin.clear();
 std::cin.ignore();
 }
  • 避免使用 C 风格 I/O:如 printf 和 scanf

4.5 性能优化建议

  • 减少复制:使用移动语义引用
  • 预分配内存:对于容器,提前分配足够的空间
 std::vector<int> vec;
 vec.reserve(1000); // 预分配空间
  • 避免频繁的内存分配:使用对象池或内存池
  • 内联函数:对于小函数,使用 inline 关键字
 inline int min(int a, int b) {
 return a < b ? a : b;
 }

5. 代码示例

5.1 温度转换

 #include <iostream>
 #include <iomanip>
 // 摄氏度转华氏度
 double celsius_to_fahrenheit(double celsius) {
  return (celsius * 9.0 / 5.0) + 32.0;
 }
 // 华氏度转摄氏度
 double fahrenheit_to_celsius(double fahrenheit) {
  return (fahrenheit - 32.0) * 5.0 / 9.0;
 }
 // 温度单位转换类
 class TemperatureConverter {
 public:
  static double celsius_to_fahrenheit(double celsius) {
  return (celsius * 9.0 / 5.0) + 32.0;
  }
  static double fahrenheit_to_celsius(double fahrenheit) {
  return (fahrenheit - 32.0) * 5.0 / 9.0;
  }
  static double celsius_to_kelvin(double celsius) {
  return celsius + 273.15;
  }
  static double kelvin_to_celsius(double kelvin) {
  return kelvin - 273.15;
  }
 }
 int main() {
  double c, f, k;
  std::cout << "输入摄氏度: ";
  std::cin >> c;
  f = TemperatureConverter::celsius_to_fahrenheit(c);
  k = TemperatureConverter::celsius_to_kelvin(c);
  std::cout << std::fixed << std::setprecision(2);
  std::cout << c << "°C = " << f << "°F = " << k << "K" << std::endl;
  std::cout << "输入华氏度: ";
  std::cin >> f;
  c = TemperatureConverter::fahrenheit_to_celsius(f);
  k = TemperatureConverter::celsius_to_kelvin(c);
  std::cout << f << "°F = " << c << "°C = " << k << "K" << std::endl;
  return 0;
 }

5.2 素数判断

 #include <iostream>
 #include <cmath>
 #include <vector>
 // 单个素数判断
 bool is_prime(int n) {
  if (n <= 1) return false;
  if (n == 2) return true;
  if (n % 2 == 0) return false;
  int sqrt_n = sqrt(n);
  for (int i = 3; i <= sqrt_n; i += 2) {
  if (n % i == 0) return false;
  }
  return true;
 }
 // 埃拉托斯特尼筛法生成素数列表
 std::vector<int> sieve_of_eratosthenes(int max) {
  std::vector<bool> is_prime(max + 1, true);
  std::vector<int> primes;
  is_prime[0] = is_prime[1] = false;
  for (int i = 2; i <= max; ++i) {
  if (is_prime[i]) {
  primes.push_back(i);
  for (int j = i * 2; j <= max; j += i) {
  is_prime[j] = false;
  }
  }
  }
  return primes;
 }
 // 素数工具类
 class PrimeUtils {
 public:
  static bool is_prime(int n) {
  if (n <= 1) return false;
  if (n == 2) return true;
  if (n % 2 == 0) return false;
  int sqrt_n = sqrt(n);
  for (int i = 3; i <= sqrt_n; i += 2) {
  if (n % i == 0) return false;
  }
  return true;
  }
  static std::vector<int> sieve_of_eratosthenes(int max) {
  std::vector<bool> is_prime(max + 1, true);
  std::vector<int> primes;
  is_prime[0] = is_prime[1] = false;
  for (int i = 2; i <= max; ++i) {
  if (is_prime[i]) {
  primes.push_back(i);
  for (int j = i * 2; j <= max; j += i) {
  is_prime[j] = false;
  }
  }
  }
  return primes;
  }
  static int count_primes(int max) {
  auto primes = sieve_of_eratosthenes(max);
  return primes.size();
  }
 }
 int main() {
  int n;
  std::cout << "输入一个整数: ";
  std::cin >> n;
  if (PrimeUtils::is_prime(n)) {
  std::cout << n << " 是素数" << std::endl;
  } else {
  std::cout << n << " 不是素数" << std::endl;
  }
  int max;
  std::cout << "输入最大值,生成素数列表: ";
  std::cin >> max;
  auto primes = PrimeUtils::sieve_of_eratosthenes(max);
  std::cout << "小于等于 " << max << " 的素数有 " << primes.size() << " 个: " << std::endl;
  for (int prime : primes) {
  std::cout << prime << " ";
  }
  std::cout << std::endl;
  return 0;
 }

5.3 数组操作

 #include <iostream>
 #include <vector>
 #include <algorithm>
 #include <numeric>
 // 计算数组和
 int sum_array(const std::vector<int>& arr) {
  int sum = 0;
  for (int num : arr) {
  sum += num;
  }
  return sum;
 }
 // 使用标准库计算数组和
 int sum_array_std(const std::vector<int>& arr) {
  return std::accumulate(arr.begin(), arr.end(), 0);
 }
 // 查找最大值
 int find_max(const std::vector<int>& arr) {
  if (arr.empty()) {
  throw std::runtime_error("Array is empty");
  }
  int max = arr[0];
  for (int num : arr) {
  if (num > max) {
  max = num;
  }
  }
  return max;
 }
 // 使用标准库查找最大值
 int find_max_std(const std::vector<int>& arr) {
  if (arr.empty()) {
  throw std::runtime_error("Array is empty");
  }
  return *std::max_element(arr.begin(), arr.end());
 }
 // 数组排序
 void sort_array(std::vector<int>& arr) {
  std::sort(arr.begin(), arr.end());
 }
 // 数组去重
 std::vector<int> remove_duplicates(const std::vector<int>& arr) {
  std::vector<int> result = arr;
  std::sort(result.begin(), result.end());
  auto last = std::unique(result.begin(), result.end());
  result.erase(last, result.end());
  return result;
 }
 // 数组工具类
 class ArrayUtils {
 public:
  static int sum(const std::vector<int>& arr) {
  return std::accumulate(arr.begin(), arr.end(), 0);
  }
  static int max(const std::vector<int>& arr) {
  if (arr.empty()) {
  throw std::runtime_error("Array is empty");
  }
  return *std::max_element(arr.begin(), arr.end());
  }
  static int min(const std::vector<int>& arr) {
  if (arr.empty()) {
  throw std::runtime_error("Array is empty");
  }
  return *std::min_element(arr.begin(), arr.end());
  }
  static double average(const std::vector<int>& arr) {
  if (arr.empty()) {
  throw std::runtime_error("Array is empty");
  }
  int sum = std::accumulate(arr.begin(), arr.end(), 0);
  return static_cast<double>(sum) / arr.size();
  }
  static void sort(std::vector<int>& arr, bool ascending = true) {
  if (ascending) {
  std::sort(arr.begin(), arr.end());
  } else {
  std::sort(arr.begin(), arr.end(), std::greater<int>());
  }
  }
  static std::vector<int> reverse(const std::vector<int>& arr) {
  std::vector<int> result = arr;
  std::reverse(result.begin(), result.end());
  return result;
  }
 }
 int main() {
  std::vector<int> numbers = {1, 5, 3, 9, 2, 5, 8, 3};
  std::cout << "原始数组: ";
  for (int num : numbers) {
  std::cout << num << " ";
  }
  std::cout << std::endl;
  std::cout << "数组和: " << ArrayUtils::sum(numbers) << std::endl;
  std::cout << "最大值: " << ArrayUtils::max(numbers) << std::endl;
  std::cout << "最小值: " << ArrayUtils::min(numbers) << std::endl;
  std::cout << "平均值: " << ArrayUtils::average(numbers) << std::endl;
  // 排序
  ArrayUtils::sort(numbers);
  std::cout << "排序后: ";
  for (int num : numbers) {
  std::cout << num << " ";
  }
  std::cout << std::endl;
  // 去重
  auto unique_numbers = remove_duplicates(numbers);
  std::cout << "去重后: ";
  for (int num : unique_numbers) {
  std::cout << num << " ";
  }
  std::cout << std::endl;
  // 反转
  auto reversed = ArrayUtils::reverse(numbers);
  std::cout << "反转后: ";
  for (int num : reversed) {
  std::cout << num << " ";
  }
  std::cout << std::endl;
  return 0;
 }

5.4 字符串操作

 #include <iostream>
 #include <string>
 #include <algorithm>
 #include <cctype>
 // 字符串工具类
 class StringUtils {
 public:
  // 字符串反转
  static std::string reverse(const std::string& str) {
  std::string result = str;
  std::reverse(result.begin(), result.end());
  return result;
  }
  // 字符串转大写
  static std::string to_upper(const std::string& str) {
  std::string result = str;
  std::transform(result.begin(), result.end(), result.begin(),
  [](unsigned char c) { return std::toupper(c); });
  return result;
  }
  // 字符串转小写
  static std::string to_lower(const std::string& str) {
  std::string result = str;
  std::transform(result.begin(), result.end(), result.begin(),
  [](unsigned char c) { return std::tolower(c); });
  return result;
  }
  // 去除首尾空格
  static std::string trim(const std::string& str) {
  size_t start = str.find_first_not_of(" \t\n\r");
  if (start == std::string::npos) return "";
  size_t end = str.find_last_not_of(" \t\n\r");
  return str.substr(start, end - start + 1);
  }
  // 检查是否是回文
  static bool is_palindrome(const std::string& str) {
  std::string cleaned;
  for (char c : str) {
  if (std::isalnum(c)) {
  cleaned += std::tolower(c);
  }
  }
  std::string reversed = cleaned;
  std::reverse(reversed.begin(), reversed.end());
  return cleaned == reversed;
  }
  // 统计单词数量
  static int count_words(const std::string& str) {
  int count = 0;
  bool in_word = false;
  for (char c : str) {
  if (std::isspace(c)) {
  in_word = false;
  } else if (!in_word) {
  in_word = true;
  count++;
  }
  }
  return count;
  }
 }
 int main() {
  std::string text = " Hello, World! ";
  std::cout << "原始字符串: '" << text << "'" << std::endl;
  std::cout << "去除空格: '" << StringUtils::trim(text) << "'" << std::endl;
  std::cout << "大写: '" << StringUtils::to_upper(text) << "'" << std::endl;
  std::cout << "小写: '" << StringUtils::to_lower(text) << "'" << std::endl;
  std::cout << "反转: '" << StringUtils::reverse(text) << "'" << std::endl;
  std::string palindrome = "A man a plan a canal Panama";
  std::cout << "是否回文: '" << palindrome << "' -> "
  << (StringUtils::is_palindrome(palindrome) ? "是" : "否") << std::endl;
  std::string sentence = "This is a test sentence";
  std::cout << "单词数量: '" << sentence << "' -> "
  << StringUtils::count_words(sentence) << std::endl;
  return 0;
 }

更新日志 (Changelog)

  • 2026-05-27: 从 C13_102 拆分,专注于型系统(常量、类型推导类型别名、最佳实践、代码示例)。