C++ 进阶知识点详细教程 - 第1部分

C++ 进阶知识点详细教程 - 第1部分

1. do while 循环

1.1 基本语法

do {
    // 循环体
} while (条件);

关键特点:至少执行一次循环体,因为条件判断在循环体执行之后。

1.2 与while循环的区别

// while循环:先判断条件,再执行
int i = 10;
while (i < 5) {
    cout << i << endl;  // 不会执行,因为10 < 5为false
}

// do-while循环:先执行,再判断条件
int j = 10;
do {
    cout << j << endl;  // 会执行一次,输出10
} while (j < 5);        // 然后判断10 < 5为false,退出循环

1.3 实际应用场景

场景1:菜单程序

#include <iostream>
using namespace std;

int main() {
    int choice;
    do {
        cout << "======= 主菜单 =======" << endl;
        cout << "1. 新建文件" << endl;
        cout << "2. 打开文件" << endl;
        cout << "3. 保存文件" << endl;
        cout << "0. 退出程序" << endl;
        cout << "请选择: ";
        cin >> choice;
        
        switch (choice) {
            case 1: cout << "新建文件成功!" << endl; break;
            case 2: cout << "打开文件成功!" << endl; break;
            case 3: cout << "保存文件成功!" << endl; break;
            case 0: cout << "感谢使用,再见!" << endl; break;
            default: cout << "无效选择,请重新输入!" << endl;
        }
        cout << endl;
    } while (choice != 0);  // 只有选择0才退出
    
    return 0;
}

场景2:输入验证

#include <iostream>
using namespace std;

int main() {
    int score;
    do {
        cout << "请输入成绩(0-100): ";
        cin >> score;
        if (score < 0 || score > 100) {
            cout << "输入无效!成绩必须在0-100之间。" << endl;
        }
    } while (score < 0 || score > 100);
    
    cout << "你输入的成绩是: " << score << endl;
    return 0;
}

场景3:游戏循环

#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;

int main() {
    srand(time(0));
    char playAgain;
    
    do {
        int secret = rand() % 100 + 1;
        int guess, attempts = 0;
        
        cout << "\n=== 猜数字游戏 ===" << endl;
        cout << "我想了一个1-100之间的数字,你来猜!" << endl;
        
        do {
            cout << "请输入你的猜测: ";
            cin >> guess;
            attempts++;
            
            if (guess < secret) {
                cout << "太小了!再试试。" << endl;
            } else if (guess > secret) {
                cout << "太大了!再试试。" << endl;
            } else {
                cout << "恭喜你!猜对了!" << endl;
                cout << "你总共猜了 " << attempts << " 次。" << endl;
            }
        } while (guess != secret);
        
        cout << "再玩一次吗?(y/n): ";
        cin >> playAgain;
        
    } while (playAgain == 'y' || playAgain == 'Y');
    
    cout << "游戏结束,谢谢游戏!" << endl;
    return 0;
}

2. switch 语句

2.1 基本语法和规则

switch (表达式) {
    case 常量1:
        // 语句块1
        break;
    case 常量2:
        // 语句块2
        break;
    case 常量3:
        // 语句块3
        break;
    default:
        // 默认语句块(可选)
        break;
}

重要规则

  1. 表达式类型:必须是整型(int、char、short、long)或枚举类型
  2. case常量:必须是编译时常量,不能是变量
  3. case唯一性:每个case后的常量值必须唯一,不能重复
  4. break的作用:跳出switch语句,防止继续执行下一个case
  5. default位置:可以放在任何位置,通常放在最后

2.2 break的重要性

没有break的后果(case穿透)

#include <iostream>
using namespace std;

int main() {
    int day = 2;
    
    cout << "没有break的情况:" << endl;
    switch (day) {
        case 1:
            cout << "星期一" << endl;
        case 2:
            cout << "星期二" << endl;  // 会执行这个
        case 3:
            cout << "星期三" << endl;  // 也会执行这个!
        case 4:
            cout << "星期四" << endl;  // 还会执行这个!
        default:
            cout << "其他" << endl;    // 甚至会执行这个!
    }
    
    cout << "\n有break的情况:" << endl;
    switch (day) {
        case 1:
            cout << "星期一" << endl;
            break;
        case 2:
            cout << "星期二" << endl;  // 只执行这个
            break;                     // 然后跳出switch
        case 3:
            cout << "星期三" << endl;
            break;
        case 4:
            cout << "星期四" << endl;
            break;
        default:
            cout << "其他" << endl;
            break;
    }
    
    return 0;
}

输出结果

没有break的情况:
星期二
星期三
星期四
其他

有break的情况:
星期二

2.3 case常量的限制

#include <iostream>
using namespace std;

int main() {
    int x = 10;
    int choice = 1;
    
    switch (choice) {
        case 1:           // 正确:字面常量
            cout << "选择1" << endl;
            break;
        case 2 + 3:       // 正确:常量表达式
            cout << "选择5" << endl;
            break;
        // case x:        // 错误!x是变量,不是常量
        //     cout << "选择x" << endl;
        //     break;
        // case 1:        // 错误!重复的case值
        //     cout << "重复" << endl;
        //     break;
        default:
            cout << "其他选择" << endl;
            break;
    }
    
    return 0;
}

2.4 有意的case穿透(实用技巧)

#include <iostream>
using namespace std;

int main() {
    int month;
    cout << "请输入月份(1-12): ";
    cin >> month;
    
    switch (month) {
        case 12:  // 12月
        case 1:   // 1月  
        case 2:   // 2月 - 这三个case都会执行到下面的语句
            cout << "冬季 ❄️" << endl;
            cout << "天气寒冷,注意保暖" << endl;
            break;
            
        case 3:
        case 4:
        case 5:
            cout << "春季 🌸" << endl;
            cout << "万物复苏,春暖花开" << endl;
            break;
            
        case 6:
        case 7:
        case 8:
            cout << "夏季 ☀️" << endl;
            cout << "天气炎热,注意防暑" << endl;
            break;
            
        case 9:
        case 10:
        case 11:
            cout << "秋季 🍂" << endl;
            cout << "秋高气爽,收获季节" << endl;
            break;
            
        default:
            cout << "无效的月份!请输入1-12之间的数字。" << endl;
            break;
    }
    
    return 0;
}

2.5 没有匹配case的情况

#include <iostream>
using namespace std;

int main() {
    int score = 75;
    char grade = score / 10;  // 7
    
    cout << "情况1:有default" << endl;
    switch (grade) {
        case 10:
        case 9:
            cout << "A等级" << endl;
            break;
        case 8:
            cout << "B等级" << endl;
            break;
        case 7:
            cout << "C等级" << endl;  // 会执行这个
            break;
        default:
            cout << "需要努力" << endl;
            break;
    }
    
    grade = 5;  // 改变值
    cout << "\n情况2:没有default,且没有匹配的case" << endl;
    switch (grade) {
        case 10:
        case 9:
            cout << "A等级" << endl;
            break;
        case 8:
            cout << "B等级" << endl;
            break;
        case 7:
            cout << "C等级" << endl;
            break;
        // 没有default,且grade=5没有对应的case
        // 结果:什么都不执行,直接跳过整个switch
    }
    cout << "switch执行完毕" << endl;
    
    return 0;
}

2.6 switch vs if-else 对比

特性 switch if-else
适用条件 等值比较 任意条件
性能 编译器可优化为跳转表 逐个判断
可读性 多分支时更清晰 复杂条件更灵活
支持类型 整型、字符型、枚举 任意布尔表达式
范围判断 不支持 支持

switch适用场景

// 菜单选择、状态机、字符分类等
switch (menuChoice) {
    case 1: createFile(); break;
    case 2: openFile(); break;
    case 3: saveFile(); break;
}

if-else适用场景

// 范围判断、复杂条件
if (score >= 90) {
    cout << "优秀";
} else if (score >= 80) {
    cout << "良好";
} else if (score >= 60) {
    cout << "及格";
} else {
    cout << "不及格";
}

2.7 实战示例:计算器

#include <iostream>
using namespace std;

int main() {
    double num1, num2, result;
    char op;
    
    cout << "简单计算器" << endl;
    cout << "请输入表达式 (如: 5 + 3): ";
    cin >> num1 >> op >> num2;
    
    switch (op) {
        case '+':
            result = num1 + num2;
            cout << num1 << " + " << num2 << " = " << result << endl;
            break;
            
        case '-':
            result = num1 - num2;
            cout << num1 << " - " << num2 << " = " << result << endl;
            break;
            
        case '*':
            result = num1 * num2;
            cout << num1 << " * " << num2 << " = " << result << endl;
            break;
            
        case '/':
            if (num2 != 0) {
                result = num1 / num2;
                cout << num1 << " / " << num2 << " = " << result << endl;
            } else {
                cout << "错误:除数不能为0!" << endl;
            }
            break;
            
        case '%':
            if (num2 != 0) {
                // 注意:%运算符只能用于整数
                cout << (int)num1 << " % " << (int)num2 << " = " 
                     << (int)num1 % (int)num2 << endl;
            } else {
                cout << "错误:除数不能为0!" << endl;
            }
            break;
            
        default:
            cout << "错误:不支持的运算符 '" << op << "'" << endl;
            cout << "支持的运算符:+ - * / %" << endl;
            break;
    }
    
    return 0;
}

3. 流程图

3.1 基本符号

  • 椭圆:开始/结束
  • 矩形:处理
  • 菱形:判断
  • 平行四边形:输入/输出

3.2 示例

开始 → 输入n → 判断n>0? → 是:输出正数 / 否:输出负数 → 结束

4. string 字符串

4.1 基本操作

#include <string>
string s = "Hello";
s.length()          // 长度
s.empty()           // 判空
s += " World"       // 连接
s[0]                // 访问

4.2 常用函数

s.substr(0, 5)      // 子串
s.find("World")     // 查找
s.insert(5, ",")    // 插入
s.erase(5, 6)       // 删除
s.replace(6,5,"C++")// 替换

4.3 转换

to_string(123)      // 数字→字符串
stoi("456")         // 字符串→int
stod("3.14")        // 字符串→double

5. 引用

5.1 什么是引用

引用是给已存在的变量起一个别名,引用和原变量共享同一块内存空间。

#include <iostream>
using namespace std;

int main() {
    int a = 10;
    int& ref = a;  // ref是a的引用(别名)
    
    cout << "a = " << a << endl;        // 10
    cout << "ref = " << ref << endl;    // 10
    cout << "&a = " << &a << endl;      // 地址相同
    cout << "&ref = " << &ref << endl;  // 地址相同
    
    ref = 20;  // 修改ref就是修改a
    cout << "修改ref后,a = " << a << endl;  // 20
    
    return 0;
}

5.2 引用的特点

  1. 必须初始化:声明引用时必须立即初始化
  2. 不能重新绑定:引用一旦绑定到某个变量就不能改变
  3. 没有独立内存:引用不占用额外的内存空间
  4. 不能为NULL:引用必须指向一个有效的对象
int a = 10, b = 20;

// 正确的引用声明
int& ref1 = a;      // 必须初始化

// 错误的引用声明
// int& ref2;       // 错误:引用必须初始化
// int& ref3 = NULL; // 错误:引用不能为NULL

// 引用不能重新绑定
ref1 = b;           // 这不是让ref1指向b,而是把b的值赋给a
cout << a << endl;  // 输出20,a的值被改变了

5.3 引用 vs 指针

特性 引用 指针
初始化 必须初始化 可以不初始化
重新指向 不能改变指向 可以改变指向
内存占用 不占用额外空间 占用指针大小的空间
NULL值 不能为NULL 可以为NULL
运算 不能进行指针运算 可以进行指针运算
使用方式 直接使用 需要解引用(*)
#include <iostream>
using namespace std;

int main() {
    int a = 10, b = 20;
    
    // 指针的使用
    int* ptr = &a;      // 指针指向a
    cout << *ptr << endl;  // 通过指针访问a的值:10
    ptr = &b;           // 指针可以改变指向
    cout << *ptr << endl;  // 现在指向b:20
    
    // 引用的使用
    int& ref = a;       // 引用绑定到a
    cout << ref << endl;   // 直接访问:10
    ref = b;            // 这是赋值,不是改变引用指向
    cout << a << endl;     // a变成了20
    cout << ref << endl;   // ref仍然是a的别名:20
    
    return 0;
}

5.4 函数参数:形参与实参

5.4.1 传值调用(值传递)

#include <iostream>
using namespace std;

// 形参:函数定义中的参数
void func1(int x) {  // x是形参
    x = 100;         // 只修改形参的副本
    cout << "函数内x = " << x << endl;
}

int main() {
    int a = 10;      // a是实参
    cout << "调用前a = " << a << endl;  // 10
    func1(a);        // 传递a的值给形参x
    cout << "调用后a = " << a << endl;  // 10(没有改变)
    return 0;
}

输出结果

调用前a = 10
函数内x = 100
调用后a = 10

5.4.2 引用传递

#include <iostream>
using namespace std;

// 形参是引用类型
void func2(int& x) {  // x是实参的引用
    x = 100;          // 直接修改实参
    cout << "函数内x = " << x << endl;
}

int main() {
    int a = 10;
    cout << "调用前a = " << a << endl;  // 10
    func2(a);         // 传递a的引用给形参x
    cout << "调用后a = " << a << endl;  // 100(被修改了)
    return 0;
}

输出结果

调用前a = 10
函数内x = 100
调用后a = 100

5.4.3 指针传递

#include <iostream>
using namespace std;

// 形参是指针类型
void func3(int* x) {  // x是指向int的指针
    *x = 100;         // 通过指针修改实参
    cout << "函数内*x = " << *x << endl;
}

int main() {
    int a = 10;
    cout << "调用前a = " << a << endl;  // 10
    func3(&a);        // 传递a的地址给形参x
    cout << "调用后a = " << a << endl;  // 100(被修改了)
    return 0;
}

5.5 实用的引用应用

5.5.1 交换函数

#include <iostream>
using namespace std;

// 错误的交换函数(值传递)
void wrongSwap(int a, int b) {
    int temp = a;
    a = b;
    b = temp;
    // 只交换了形参的副本,实参不变
}

// 正确的交换函数(引用传递)
void correctSwap(int& a, int& b) {
    int temp = a;
    a = b;
    b = temp;
    // 直接交换实参
}

int main() {
    int x = 10, y = 20;
    
    cout << "交换前: x=" << x << ", y=" << y << endl;
    wrongSwap(x, y);
    cout << "错误交换后: x=" << x << ", y=" << y << endl;
    
    correctSwap(x, y);
    cout << "正确交换后: x=" << x << ", y=" << y << endl;
    
    return 0;
}

5.5.2 避免大对象的复制

#include <iostream>
#include <vector>
#include <string>
using namespace std;

// 低效:传值会复制整个vector
void printVector1(vector<int> v) {  // 复制开销大
    cout << "Vector size: " << v.size() << endl;
    for (int x : v) cout << x << " ";
    cout << endl;
}

// 高效:传引用不复制
void printVector2(const vector<int>& v) {  // const防止修改
    cout << "Vector size: " << v.size() << endl;
    for (int x : v) cout << x << " ";
    cout << endl;
}

// 可以修改的引用传递
void addOne(vector<int>& v) {
    for (int& x : v) {  // 注意这里也用引用
        x++;
    }
}

int main() {
    vector<int> nums = {1, 2, 3, 4, 5};
    
    printVector2(nums);  // 高效的只读访问
    addOne(nums);        // 修改vector
    printVector2(nums);  // 再次查看
    
    return 0;
}

5.5.3 返回多个值

#include <iostream>
using namespace std;

// 通过引用参数返回多个值
void divideWithRemainder(int dividend, int divisor, 
                        int& quotient, int& remainder) {
    quotient = dividend / divisor;
    remainder = dividend % divisor;
}

// 解二次方程 ax² + bx + c = 0
bool solveQuadratic(double a, double b, double c,
                   double& x1, double& x2) {
    double discriminant = b * b - 4 * a * c;
    if (discriminant < 0) {
        return false;  // 无实数解
    }
    
    x1 = (-b + sqrt(discriminant)) / (2 * a);
    x2 = (-b - sqrt(discriminant)) / (2 * a);
    return true;
}

int main() {
    // 除法示例
    int q, r;
    divideWithRemainder(17, 5, q, r);
    cout << "17 ÷ 5 = " << q << " 余 " << r << endl;
    
    // 二次方程示例
    double root1, root2;
    if (solveQuadratic(1, -5, 6, root1, root2)) {
        cout << "方程 x² - 5x + 6 = 0 的解:" << endl;
        cout << "x1 = " << root1 << ", x2 = " << root2 << endl;
    }
    
    return 0;
}

5.6 常引用(const引用)

#include <iostream>
#include <string>
using namespace std;

int main() {
    int a = 10;
    const int& ref = a;  // 常引用,不能通过ref修改a
    
    cout << ref << endl;  // 可以读取
    // ref = 20;          // 错误:不能修改
    
    a = 20;               // 可以直接修改a
    cout << ref << endl;  // ref会反映a的变化:20
    
    // 常引用可以绑定到字面量
    const int& ref2 = 100;  // 正确
    // int& ref3 = 100;     // 错误:非常引用不能绑定字面量
    
    return 0;
}

常引用的优势

  1. 可以接受字面量和临时对象
  2. 防止意外修改
  3. 提高代码安全性
// 函数参数使用常引用
void printString(const string& s) {  // 高效且安全
    cout << s << endl;
    // s += "!";  // 错误:不能修改
}

int main() {
    string name = "Alice";
    printString(name);        // 传递变量
    printString("Bob");       // 传递字面量
    printString(name + "!");  // 传递临时对象
    return 0;
}

6. 联合体(Union)

6.1 什么是联合体

联合体是一种特殊的数据类型,所有成员共享同一块内存空间。同一时刻只能存储其中一个成员的值。

#include <iostream>
using namespace std;

union Data {
    int i;      // 4字节
    float f;    // 4字节
    char c;     // 1字节
};  // 联合体大小 = 最大成员的大小 = 4字节

int main() {
    Data d;
    
    cout << "联合体大小: " << sizeof(d) << " 字节" << endl;  // 4
    cout << "int大小: " << sizeof(d.i) << " 字节" << endl;   // 4
    cout << "float大小: " << sizeof(d.f) << " 字节" << endl; // 4
    cout << "char大小: " << sizeof(d.c) << " 字节" << endl;  // 1
    
    return 0;
}

6.2 联合体的内存共享

#include <iostream>
using namespace std;

union Data {
    int i;
    float f;
    char c;
};

int main() {
    Data d;
    
    // 存储整数
    d.i = 1000;
    cout << "存储整数后:" << endl;
    cout << "d.i = " << d.i << endl;     // 1000
    cout << "d.f = " << d.f << endl;     // 垃圾值
    cout << "d.c = " << (int)d.c << endl; // 垃圾值
    
    // 存储浮点数(覆盖之前的整数)
    d.f = 3.14f;
    cout << "\n存储浮点数后:" << endl;
    cout << "d.i = " << d.i << endl;     // 垃圾值
    cout << "d.f = " << d.f << endl;     // 3.14
    cout << "d.c = " << (int)d.c << endl; // 垃圾值
    
    // 存储字符(覆盖之前的浮点数)
    d.c = 'A';
    cout << "\n存储字符后:" << endl;
    cout << "d.i = " << d.i << endl;     // 垃圾值
    cout << "d.f = " << d.f << endl;     // 垃圾值
    cout << "d.c = " << d.c << endl;     // A
    
    return 0;
}

6.3 联合体 vs 结构体

#include <iostream>
using namespace std;

// 结构体:每个成员有独立的内存
struct StructData {
    int i;      // 偏移0,4字节
    float f;    // 偏移4,4字节
    char c;     // 偏移8,1字节
    // 总大小:12字节(考虑内存对齐)
};

// 联合体:所有成员共享内存
union UnionData {
    int i;      // 偏移0,4字节
    float f;    // 偏移0,4字节
    char c;     // 偏移0,1字节
    // 总大小:4字节(最大成员)
};

int main() {
    StructData s;
    UnionData u;
    
    cout << "结构体大小: " << sizeof(s) << " 字节" << endl;  // 12
    cout << "联合体大小: " << sizeof(u) << " 字节" << endl;  // 4
    
    // 结构体:每个成员独立
    s.i = 100;
    s.f = 3.14f;
    s.c = 'X';
    cout << "\n结构体存储后:" << endl;
    cout << "s.i = " << s.i << endl;  // 100
    cout << "s.f = " << s.f << endl;  // 3.14
    cout << "s.c = " << s.c << endl;  // X
    
    // 联合体:只能存储一个值
    u.i = 100;
    cout << "\n联合体存储整数后:" << endl;
    cout << "u.i = " << u.i << endl;  // 100
    
    u.f = 3.14f;  // 覆盖之前的整数
    cout << "\n联合体存储浮点数后:" << endl;
    cout << "u.f = " << u.f << endl;  // 3.14
    cout << "u.i = " << u.i << endl;  // 垃圾值
    
    return 0;
}

6.4 联合体的实际应用

6.4.1 节省内存空间

#include <iostream>
using namespace std;

// 一个变量在不同时刻需要不同类型的值
enum DataType { INT_TYPE, FLOAT_TYPE, CHAR_TYPE };

struct Variable {
    DataType type;  // 记录当前存储的类型
    union {
        int intVal;
        float floatVal;
        char charVal;
    } value;
};

void printVariable(const Variable& var) {
    switch (var.type) {
        case INT_TYPE:
            cout << "整数: " << var.value.intVal << endl;
            break;
        case FLOAT_TYPE:
            cout << "浮点数: " << var.value.floatVal << endl;
            break;
        case CHAR_TYPE:
            cout << "字符: " << var.value.charVal << endl;
            break;
    }
}

int main() {
    Variable var;
    
    // 存储整数
    var.type = INT_TYPE;
    var.value.intVal = 42;
    printVariable(var);
    
    // 存储浮点数
    var.type = FLOAT_TYPE;
    var.value.floatVal = 3.14f;
    printVariable(var);
    
    // 存储字符
    var.type = CHAR_TYPE;
    var.value.charVal = 'A';
    printVariable(var);
    
    return 0;
}

6.4.2 类型转换和位操作

#include <iostream>
#include <iomanip>
using namespace std;

// 查看浮点数的二进制表示
union FloatBits {
    float f;
    unsigned int bits;
};

// IP地址的不同表示
union IPAddress {
    unsigned int addr;      // 32位整数表示
    unsigned char bytes[4]; // 4个字节表示
};

int main() {
    // 浮点数位表示
    FloatBits fb;
    fb.f = 3.14f;
    cout << "浮点数 " << fb.f << " 的二进制表示: " 
         << hex << fb.bits << dec << endl;
    
    // IP地址转换
    IPAddress ip;
    ip.bytes[0] = 192;
    ip.bytes[1] = 168;
    ip.bytes[2] = 1;
    ip.bytes[3] = 100;
    
    cout << "IP地址: " 
         << (int)ip.bytes[0] << "."
         << (int)ip.bytes[1] << "."
         << (int)ip.bytes[2] << "."
         << (int)ip.bytes[3] << endl;
    
    cout << "32位表示: " << ip.addr << endl;
    
    return 0;
}

6.4.3 网络数据包解析

#include <iostream>
using namespace std;

// 网络数据包头部
union PacketHeader {
    struct {
        unsigned char version : 4;    // 版本号(4位)
        unsigned char headerLen : 4;  // 头部长度(4位)
        unsigned char typeOfService;  // 服务类型(8位)
        unsigned short totalLength;   // 总长度(16位)
    } fields;
    unsigned int raw;  // 原始32位数据
};

// 颜色的不同表示
union Color {
    struct {
        unsigned char r, g, b, a;  // RGBA分量
    } rgba;
    unsigned int value;  // 32位颜色值
};

int main() {
    // 颜色示例
    Color color;
    color.rgba.r = 255;  // 红色分量
    color.rgba.g = 128;  // 绿色分量
    color.rgba.b = 0;    // 蓝色分量
    color.rgba.a = 255;  // 透明度
    
    cout << "颜色 RGB(" << (int)color.rgba.r << ", " 
         << (int)color.rgba.g << ", " << (int)color.rgba.b << ")" << endl;
    cout << "32位值: " << hex << color.value << dec << endl;
    
    return 0;
}

6.5 匿名联合体

#include <iostream>
using namespace std;

struct Point {
    int type;  // 点的类型
    union {    // 匿名联合体
        struct { int x, y; } point2D;      // 2D坐标
        struct { int x, y, z; } point3D;   // 3D坐标
        int coordinates[3];                 // 数组形式
    };  // 注意分号
};

int main() {
    Point p;
    p.type = 2;  // 2D点
    
    // 直接访问联合体成员,不需要联合体名称
    p.point2D.x = 10;
    p.point2D.y = 20;
    
    cout << "2D点: (" << p.point2D.x << ", " << p.point2D.y << ")" << endl;
    
    // 也可以通过数组访问
    cout << "通过数组: (" << p.coordinates[0] << ", " 
         << p.coordinates[1] << ")" << endl;
    
    return 0;
}

6.6 联合体的注意事项

  1. 类型安全:程序员需要记住当前存储的是哪种类型
  2. 初始化:只能初始化第一个成员
  3. 构造函数:C++11后联合体可以有构造函数和析构函数
  4. 内存对齐:联合体的大小会考虑最严格的对齐要求
#include <iostream>
using namespace std;

union Data {
    int i;
    double d;    // 8字节,需要8字节对齐
    char c;
};

int main() {
    Data d1 = {100};  // 只能初始化第一个成员
    cout << "d1.i = " << d1.i << endl;
    
    // Data d2 = {3.14};  // 错误:不能初始化第二个成员
    
    cout << "联合体大小: " << sizeof(Data) << " 字节" << endl;  // 8字节
    
    return 0;
}

6.7 现代C++中的联合体

C++17引入了std::variant作为类型安全的联合体替代:

#include <iostream>
#include <variant>
#include <string>
using namespace std;

int main() {
    // 类型安全的联合体
    variant<int, float, string> v;
    
    v = 42;
    cout << "整数: " << get<int>(v) << endl;
    
    v = 3.14f;
    cout << "浮点数: " << get<float>(v) << endl;
    
    v = string("Hello");
    cout << "字符串: " << get<string>(v) << endl;
    
    return 0;
}

联合体总结

  • 优点:节省内存,适合嵌入式系统
  • 缺点:类型不安全,需要程序员管理
  • 现代替代std::variant提供类型安全的选择
posted @ 2025-11-14 17:23  surprise_ying  阅读(0)  评论(0)    收藏  举报