2.1变量与基本数据类型

60 阅读5分钟

变量与基本数据类型:C++世界的积木块

一、基础数据类型详解(类比:变量是程序世界的储物柜)

1. 整型家族

int age = 25;                    // 常规整数(通常4字节)
short score = 100;               // 短整型(2字节)
long population = 7800000000L;   // 长整型(4或8字节)
long long stars = 1'000'000'000'000LL;  // C++11分隔符
​
// C++11固定宽度类型
#include <cstdint>
int32_t precise_width = 42;      // 精确4字节
uint8_t byte_data = 0xFF;        // 无符号字节

取值范围对照表

类型典型字节取值范围
int4-2,147,483,648 ~ 2,147,483,647
uint32_t40 ~ 4,294,967,295
int64_t8-9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807

2. 浮点型精度

float pi_approx = 3.14159f;     // 单精度(6-7位有效数字)
double earth_mass = 5.9722e24;  // 双精度(15位有效数字)
long double precise = 3.141592653589793238L;  // 扩展精度

3. 字符与布尔

char grade = 'A';               // ASCII字符(1字节)
wchar_t wide_char = L'中';       // 宽字符(2/4字节)
char16_t utf16_char = u'好';     // C++11 Unicode字符
bool is_valid = true;           // 布尔值(true/false)

二、变量使用规范(类比:编程界的交通规则)

1. 命名最佳实践

// 好的命名
int student_count{};          // 蛇形命名法
double averageScore{};        // 驼峰命名法
auto& db_connection = get_db();  // 含义明确// 坏的命名
int a;                        // 无意义
double dbl;                   // 类型缩写冗余
int foo_bar;                  // 不明确含义

2. 作用域层级

int global_var = 10;  // 全局变量(慎用!)void demo() {
    int local_var = 20;       // 函数作用域
    static int persist = 5;   // 静态局部变量
    
    if (true) {
        int block_var = 30;   // 块作用域
        // global_var 在此可见
    }
    // block_var 在此不可见
}
​
// C++17起支持inline变量
inline int shared_config = 42;

作用域可见性矩阵:

变量类型文件内可见函数内可见块内可见
全局变量
静态全局变量
局部变量
块变量

三、常量使用之道(编译时 vs 运行时)

1. const常量

const int MAX_RETRY = 3;          // 运行时常量
const double PI = calculate_pi(); // 需要运行时计算void process(const std::string& input) {  // 常量引用
    // input 在此不可修改
}

2. constexpr常量(C++11起)

constexpr int BUFFER_SIZE = 1024;  // 编译期常量
constexpr double COMPILE_TIME_PI = 3.1415926;
​
constexpr int factorial(int n) {   // C++11 constexpr函数
    return n <= 1 ? 1 : n * factorial(n-1);
}
​
int main() {
    int arr[factorial(5)];  // 编译期计算数组大小
    static_assert(BUFFER_SIZE > 100, "Buffer太小!"); // 编译期断言
}

const vs constexpr对比表:

特性constconstexpr
初始化时机运行时编译时
可用场景变量/函数变量/函数/对象
类型要求任意字面类型
内存分配可能分配可能优化掉

四、新手常见问题解答

Q:该用int还是size_t? A:遵循以下原则:

  • 需要表示大小/索引 → size_t
  • 需要负数 → int32_t
  • 内存敏感场景 → 明确指定位宽

Q:全局变量有什么危害? A:主要问题:

  1. 命名空间污染
  2. 多线程安全问题
  3. 代码耦合度高 替代方案:使用单例模式或命名空间封装

Q:为什么提倡用constexpr? A:三大优势:

  1. 编译期计算提升性能
  2. 支持静态断言检查
  3. 可用于模板元编程

五、实战技巧宝典

1. 初始化最佳实践

int x{};          // 值初始化(0)
double y{3.14};   // 统一初始化
auto z = int{5};  // 明确类型// 避免最恼人的解析问题
std::vector<int> data(10);    // 创建10个元素的vector
std::vector<int> data{10};    // 创建1个元素值为10的vector

2. 类型推断妙用

auto i = 42;          // int
auto d = 3.14;        // double
auto s = "hello";     // const char*
auto& vec = get_data(); // 引用推断// 结构化绑定(C++17)
std::tuple<int, double, std::string> get_record();
auto [id, score, name] = get_record();

3. 作用域管理工具

// IIFE(立即调用函数表达式)
const auto config = []{
    Config cfg;
    cfg.load("settings.json");
    cfg.validate();
    return cfg;
}();  // 立即执行并初始化// 块作用域限制可见性
void process_data() {
    {
        TempFile temp("data.bin");
        // temp仅在块内有效
    } // 自动释放资源
}

4. 类型转换建议

double pi = 3.14159;
int approx = static_cast<int>(pi);  // 推荐C++风格转换// 避免C风格转换
int dangerous = (int)"hello";     // 编译通过但危险!
int safe = static_cast<int>(reinterpret_cast<uintptr_t>("hello")); // 明确意图

六、学习路径推荐

  1. 基础阶段(1-2周)

    • 掌握所有基础类型的内存占用
    • 完成50个变量命名练习
    • 理解作用域链规则
  2. 进阶阶段(3-4周)

    • 学习类型推导机制
    • 掌握const正确性
    • 实践编译期常量优化
  3. 高手之路(1-2月)

    • 研究类型特征(type traits)
    • 实现自定义字面量
    • 掌握移动语义与完美转发

推荐练习项目:

  • 实现单位转换器(类型转换实践)
  • 开发配置管理器(常量使用)
  • 编写数学函数库(类型通用性)

变量与数据类型就像编程世界的原子,掌握它们的特性是构建复杂程序的基石。从简单的整型到编译期常量,从局部作用域到类型推导,每个特性都是为了让代码更安全、更高效。记住:好的变量命名是给半年后的自己写情书,合理的类型选择是对程序性能的最佳投资。