c++ union使用笔记

c++ union使用笔记

C++联合(union)是一种特殊的数据结构,允许在相同内存位置存储不同的数据类型,其核心价值在于 节省内存空间 (所有成员共享同一块内存)。以下是联合的详细说明和应用示例:


一、联合的简单使用

特点

  • 所有成员共享同一块内存(大小为最大成员的大小)
  • 同一时间只能使用一个成员
  • 默认访问权限为 public

示例

cpp 复制代码
union NumericData {
    int i;
    double d;
    char c;
};

int main() {
    NumericData data;
    data.i = 42;                // 存储整数
    std::cout << data.i << "\n"; // 输出 42
    
    data.d = 3.14;              // 覆盖内存,存储双精度浮点数
    std::cout << data.d << "\n"; // 输出 3.14
    
    // 注意:此时访问 data.i 将得到无意义的值!
    return 0;
}

二、联合与枚举结合

核心思想:通过枚举标记联合当前存储的数据类型,避免错误访问。

示例1

cpp 复制代码
// 定义数据类型标签
enum class DataType { INT, DOUBLE, CHAR };

struct DataContainer {
    DataType tag; // 类型标记
    union {
        int i;
        double d;
        char c;
    };
};

int main() {
    DataContainer dc;
    dc.tag = DataType::INT;
    dc.i = 100;

    // 安全访问:先检查类型标记
    if (dc.tag == DataType::INT) {
        std::cout << dc.i << "\n"; // 输出 100
    }

    dc.tag = DataType::DOUBLE;
    dc.d = 2.718;
    // 错误示例:未检查标记直接访问将导致未定义行为
    return 0;
}

示例2

cpp 复制代码
#include <iostream>
#include <string>

enum class DataType { INT, DOUBLE, STRING };

struct Variant {
    DataType type;
    union {
        int i;
        double d;
        std::string s;
    };

    // 构造函数
    Variant(int val) : type(DataType::INT), i(val) {}
    Variant(double val) : type(DataType::DOUBLE), d(val) {}
    Variant(const std::string& val) : type(DataType::STRING) {
        new (&s) std::string(val); // Placement new 构造字符串
    }

    // 析构函数
    ~Variant() {
        if (type == DataType::STRING) {
            s.~basic_string(); // 手动析构字符串
        }
    }

    // 拷贝构造函数
    Variant(const Variant& other) : type(other.type) {
        switch (type) {
            case DataType::INT: i = other.i; break;
            case DataType::DOUBLE: d = other.d; break;
            case DataType::STRING: new (&s) std::string(other.s); break;
        }
    }

    // 赋值运算符
    Variant& operator=(const Variant& other) {
        if (this != &other) {
            if (type == DataType::STRING) s.~basic_string();
            type = other.type;
            switch (type) {
                case DataType::INT: i = other.i; break;
                case DataType::DOUBLE: d = other.d; break;
                case DataType::STRING: new (&s) std::string(other.s); break;
            }
        }
        return *this;
    }
};

三、匿名联合(Anonymous Union)

特点

  • 没有名称,直接访问成员
  • 常用于结构体或类内部简化访问
  • C++11 起允许包含非平凡类型(如 string,但需谨慎使用)

示例

cpp 复制代码
struct Data {
    enum { INT, FLOAT } type;
    union { // 匿名联合
        int i;
        float f;
    };
};

// 使用示例
Data d;
d.type = Data::INT;
d.i = 42; // 直接访问匿名联合成员

四、关键注意事项

  1. 内存覆盖:修改一个成员会影响其他成员的值。
  2. 类型安全:必须手动跟踪当前有效成员(通常结合枚举)。
  3. 构造/析构:C++11 起支持含有非平凡类型的联合,但需显式管理生命周期。
  4. 应用场景
    • 协议解析(如网络数据包)
    • 硬件寄存器映射
    • 内存敏感型应用(嵌入式系统)

五、C++17 扩展:std::variant

对于需要更安全的类型存储,推荐使用 std::variant(C++17 引入):

cpp 复制代码
#include <variant>
#include <string>

int main() {
    std::variant<int, double, std::string> data;
    data = 42; // 存储 int
    data = "Hello"; // 存储 string
    // 自动跟踪当前类型,无需手动标记
    return 0;
}
相关推荐
Suckerbin23 分钟前
DarkHole: 2靶场渗透
笔记·安全·web安全·网络安全
岁忧28 分钟前
(LeetCode 面试经典 150 题) 200. 岛屿数量(深度优先搜索dfs || 广度优先搜索bfs)
java·c++·leetcode·面试·go·深度优先
一枝小雨36 分钟前
【OJ】C++ vector类OJ题
数据结构·c++·算法·leetcode·oj题
一枝小雨36 分钟前
【C++】Vector完全指南:动态数组高效使用
开发语言·c++·笔记·vector·学习笔记·std库
大白的编程日记.1 小时前
【Linux学习笔记】信号的深入理解之软件条件产生信号
linux·笔记·学习
buyutang_1 小时前
C/C++ Linux系统编程:线程控制详解,从线程创建到线程终止
linux·c语言·c++·学习
Wilber的技术分享1 小时前
【大模型实战笔记 1】Prompt-Tuning方法
人工智能·笔记·机器学习·大模型·llm·prompt
Qiang_san1 小时前
GNU Make | C/C++项目自动构建入门
c语言·c++·gnu
来生硬件工程师1 小时前
【硬件笔记】负载是如何烧MOS的?
笔记·嵌入式硬件·硬件架构·硬件工程·硬件设计
源代码•宸2 小时前
Leetcode—2749. 得到整数零需要执行的最少操作数【中等】(__builtin_popcountl)
c++·经验分享·算法·leetcode·位运算