struct,union,Class,bitfield各自的作用和区别

struct,union,Class,bitfield各自的作用和区别

这四个概念是 C/C++ 中构建数据结构的核心基石。简单来说,它们都是用来组织数据的,但侧重点完全不同:

  • struct :用来打包不同类型的数据(如一个"学生"包含姓名、年龄)。
  • union :用来节省内存,同一时间只能存一种数据(如"身份证"和"护照"共用一个位置)。
  • class :用来封装数据和行为,是面向对象的核心(如一个"银行账户"包含余额和存取款方法)。
  • bitfield :用来极致压缩空间,精确到"位"(如只占 1 位的开关状态)。

1. 结构体

核心作用:数据的"打包容器"

struct 是最常用的聚合类型,用于将多个不同类型的数据组合在一起,描述一个事物的属性。

  • 内存机制每个成员都有自己独立的内存空间 。结构体的总大小通常大于等于所有成员大小之和(因为存在内存对齐)。
  • 访问方式:所有成员可以同时存在并被访问。
  • C vs C++
    • C语言 :只能包含数据成员,默认为 public
    • C++ :可以包含函数、构造函数等。默认访问权限是 public (这是与 class 的主要语法区别之一)。

代码示例:

cpp 复制代码
struct Student {
    char name[20];
    int age;
    float score;
}; 
// sizeof(Student) 通常 >= 20+4+4 (受对齐影响)
// 每个成员都有独立的内存

2. 联合体

核心作用:内存的"节省神器"

union 看起来和结构体很像,但它的逻辑是"互斥"。它用于那些在同一时间只需要存储一种类型数据的场景。

  • 内存机制所有成员共用同一块内存 。联合体的总大小等于其最大成员的大小(并满足对齐要求)。
  • 访问方式:同一时间只能有一个成员是有效的。给一个成员赋值,会覆盖其他成员的数据。
  • 典型场景
    • 节省内存:在嵌入式系统中,RAM 极其宝贵。
    • 数据类型转换 :例如将 int 拆分为 4 个 char 来分析字节(大小端检测)。

代码示例:

cpp 复制代码
union Data {
    int i;
    float f;
    char str[4];
};
// sizeof(Data) = 4 (假设 int 为 4 字节,且是最大成员)
// 内存是共用的,修改 i 会影响 f 和 str 的值

3. 类

核心作用:面向对象的"蓝图"

class 是 C++ 面向对象编程(OOP)的核心。它不仅包含数据,还包含操作数据的方法(行为),强调封装、继承和多态

  • 内存机制 :与 struct 类似,成员变量占用独立内存。
  • 核心特性
    • 封装 :通过 privateprotected 隐藏内部实现细节,只暴露 public 接口。
    • 行为:可以包含构造函数、析构函数、虚函数等。
  • C++ 中与 struct 的区别
    • 默认访问权限class 的成员默认是 private 的,而 struct 默认是 public 的。
    • 默认继承方式class 默认是私有继承,struct 默认是公有继承。
    • 语义class 通常用于既有数据又有行为的复杂对象,struct 通常用于纯数据载体(POD)。

代码示例:

cpp 复制代码
class BankAccount {
private: // 默认就是 private
    double balance;
public:
    void deposit(double amount) { balance += amount; } // 行为
    double getBalance() { return balance; }
};

4. 位域

核心作用:空间的"极致压缩"

位域(Bit Field)是一种特殊的结构体或联合体成员,允许你指定成员占用的具体位数(如 1 位、3 位)。

  • 内存机制 :多个位域成员可以挤在同一个字节里。例如,两个 int:1 的成员只占 2 个位,而不是 8 个字节。
  • 典型场景
    • 嵌入式/硬件驱动:直接映射硬件寄存器(如某个寄存器第 0 位是开关,第 1-3 位是模式)。
    • 网络协议:解析 IP 头等紧凑的数据包格式。
  • 缺点可移植性差。位域的内存布局(大端/小端、对齐方式)依赖于编译器,不同编译器下结果可能不同。

代码示例:

cpp 复制代码
struct HardwareReg {
    unsigned int enable : 1;  // 只占 1 位
    unsigned int mode   : 3;  // 只占 3 位
    unsigned int error  : 1;  // 只占 1 位
    // 总共只占 5 位,通常会被塞进一个字节或 int 中
};

总结对比表

特性 struct union class bitfield
核心用途 数据打包,描述事物属性 节省内存,多类型复用 封装数据与行为 (OOP) 极致压缩,硬件映射
内存占用 各成员独立,总和+对齐 成员共用,取最大值 同 struct 按位分配,多个成员挤在一起
数据共存 ✅ 所有成员同时有效 ❌ 同一时间仅一个有效 ✅ 所有成员同时有效 ✅ 同时有效
默认访问权限 (C++) public public private (取决于所在结构)
典型场景 数据传输对象、配置项 变体数据类型、协议解析 业务对象、复杂逻辑 硬件寄存器、协议头

struct union class 都可以设置构造函数?和几个特殊的构造函数吗? 他们都可以设置private protected,public???

  1. 构造函数structclass 完全一样,都可以定义构造函数;union 也可以,但限制较多。
  2. 访问控制 :它们都可以 设置 privateprotectedpublic,区别只在于默认的权限不同。

1. 构造函数:它们都能用吗?

在 C++ 中,structunionclass 本质上都是"类类型",它们都可以拥有构造函数,但能力有所不同。

✅ struct 和 class:完全体

这两者在构造函数方面没有任何区别

  • 都可以定义默认构造函数、带参构造函数。
  • 都可以定义拷贝构造函数、移动构造函数。
  • 都可以重载 = 运算符。
  • 都可以定义析构函数。
⚠️ union:受限体

union 也可以有构造函数,但因为它特殊的内存共享机制(所有成员共用一块内存),有一些特殊规则:

  • 不能有虚函数 :因为 union 通常用于底层内存操作,不支持多态。
  • 不能有引用类型的成员:因为不同成员大小可能不同,引用无法正确绑定。
  • 不能有静态成员(C++11 之前)。
  • 如果成员有非平凡构造函数 :如果你的 union 里有一个 std::string 或者自定义类,你需要手动编写 union 的构造函数来初始化它(或者使用定位 new),编译器不会自动生成。

代码示例:

cpp 复制代码
struct MyStruct {
    MyStruct() { /* 结构体构造函数 */ }
};

class MyClass {
public:
    MyClass() { /* 类构造函数 */ }
};

union MyUnion {
    int i;
    double d;
    
    // Union 的构造函数
    MyUnion() : i(0) {} 
};

2. 访问控制:private / protected / public

答案是肯定的:它们都可以使用这三个关键字。

但是,默认的访问权限不同,这是它们在语法上最大的区别。

📊 权限对比表
特性 struct class union
默认成员权限 public (公开) private (私有) public (公开)
默认继承权限 public (公开继承) private (私有继承) (通常不用于继承)
能否用 private
能否用 protected
  1. struct 默认是"坦诚"的

    如果你不写 public:private:,编译器默认所有成员都是 public 的。这符合 C 语言遗留下来的习惯------struct 主要用来存数据,数据通常是公开访问的。

  2. class 默认是"封闭"的

    如果你不写访问修饰符,编译器默认所有成员都是 private 的。这符合面向对象编程(OOP)的封装原则------隐藏内部实现细节,只暴露接口。

  3. union 默认是"坦诚"的

    struct 一样,默认是 public

实战:如何手动设置权限

即使 struct 默认是公开的,你依然可以强制把它变成私有的;反之亦然。

在 struct 中使用 private:

cpp 复制代码
struct SecretData {
private: // 强制设为私有
    int password; 
public:
    void setPassword(int p) { password = p; }
};

在 class 中使用 public:

cpp 复制代码
class PublicConfig {
public: // 强制设为公开
    int version;
private:
    void internalLogic() {}
};

3. 几个特殊的构造函数

除了普通的构造函数,C++ 中还有几个特殊的构造函数,structclass 都可以拥有它们:

  1. 默认构造函数:无参或所有参数都有默认值。
  2. 拷贝构造函数Class(const Class& other),用于对象复制。
  3. 移动构造函数Class(Class&& other),C++11 引入,用于资源转移(高效)。
  4. 拷贝赋值运算符operator=(const Class&),虽然不是构造函数,但常与构造函数一起讨论(Rule of Three/Five)。
  5. 析构函数~Class(),对象销毁时调用。

总结:

  • 如果你想要一个纯数据载体 ,用 struct(默认 public,写起来省事)。
  • 如果你想要一个功能完备的对象 ,需要封装和继承,用 class(默认 private,更安全)。
  • 如果你需要省内存 或者做底层数据解析 ,用 union
  • 无论用哪个,你都可以手动加上 privateprotectedpublic 来控制访问权限。
相关推荐
算.子2 小时前
【Spring AI 实战】八、完整 RAG 问答实战:检索 + 重排序 + 生成全链路
java·人工智能·spring
wuminyu2 小时前
专家视角看 Java 字节码与Class 文件格式
java·linux·c语言·jvm·c++
Gauss松鼠会2 小时前
【openGauss】openGauss 磁盘引擎之 ustore
java·服务器·开发语言·前端·数据库·经验分享·gaussdb
YSF2017_32 小时前
C语言-13-制作动态库
c语言·开发语言
lee_curry2 小时前
线程中断,等待,唤醒与ThreadLocal
java·线程·juc·threadlocal·中断
John.Lewis2 小时前
Python小课(6)基础语法⑤
开发语言·python
indexsunny2 小时前
互联网大厂Java面试实战:Spring Boot微服务与Kafka消息队列深度解析
java·spring boot·微服务·面试·kafka·消息队列·电商
csgo打的菜又爱玩2 小时前
7.DispatcherResourceManagerComponentFactory解析.md
开发语言·python·flink
云深麋鹿2 小时前
C++ | 继承
开发语言·c++