struct 结构体
原理
C struct 与 C++ struct 的过渡
在 C 语言中,struct 是纯数据聚合——只能包含数据成员,不能包含函数。在 C++ 中,struct 被”升级”为与 class 几乎等价的类型构建工具。唯一区别是默认访问级别:struct 默认 public,class 默认 private。除此之外,struct 同样支持成员函数、构造/析构、虚函数、继承、多态。
// C 风格(纯数据)
struct Point { int x, y; };
// C++ 风格(带方法)
struct Point {
int x, y;
double length() const { return sqrt(x*x + y*y); }
};底层等价性
编译器对 struct 和 class 生成的汇编代码完全相同。以下两段代码产生的机器码一致:
struct S { int x; void f() { x = 1; } };
class C { public: int x; void f() { x = 1; } };这印证了一个关键事实:C++ 的访问控制(public/private)是纯编译期的概念——在运行时和汇编层面不存在任何区别或开销。
struct 内存布局
与 class 完全一致:成员按声明顺序排列;对齐规则相同(当前偏移须被成员类型大小整除);同样支持虚函数(引入 vptr 于偏移 0 处)。
struct Layout {
char a; // 1B, offset 0
int b; // 4B, offset 4 (offset 1 不整除 4 → pad 3)
short c; // 2B, offset 8
};
// sizeof(Layout) = 12 (pad 2 在末尾,确保对齐到最大类型 4)struct 约定与语义
虽然语法上 struct 可以做 class 的所有事情,但社区约定两者有明确分工:
- struct:纯数据聚合(POD 类型)。如链表节点、树节点、配置参数、坐标点。公开数据成员是自然的,不暴露封装假象
- class:有封装逻辑的类型。需要不变量保证、访问控制、资源管理的场景
这不仅是代码风格问题——struct 保持简单数据聚合的语义,让读者可以一眼判断”这个类型的成员可以直接访问,没有隐藏的副作用”。
POD 与 C 兼容性
POD(Plain Old Data)类型是可以与 C 语言二进制兼容的类型——不含虚函数、不含构造函数/析构函数、不含引用成员、不含非 POD 基类。C++11 起 POD 概念被拆分为 trivial(平凡可复制)和 standard-layout(标准布局)。纯粹的 struct 数组(如 Point pts[100])既是 trivial 也是 standard-layout,可以用 memcpy 安全复制,也可以直接传给 C 函数。
语法
聚合初始化
struct Vec3 { float x, y, z; };
Vec3 v1 = {1.0f, 2.0f, 3.0f}; // C++98
Vec3 v2{1.0f, 2.0f, 3.0f}; // C++11 统一初始化
Vec3 v3{}; // 零初始化 {0,0,0}
Vec3 v4{.x=1.0f, .z=3.0f}; // C++20 指定初始化器struct 与数据结构
struct 是构建所有数据结构的基石节点:
struct ListNode { int value; ListNode* next; };
struct TreeNode { int value; TreeNode *left, *right; };
struct HashNode { int key, value; HashNode* next; };
struct Edge { int from, to, weight; };struct 的构造/析构/继承
struct 可以拥有与 class 完全相同的构造体系:
struct Base {
int id;
Base(int i) : id(i) {}
virtual ~Base() = default;
};
struct Derived : Base {
double val;
Derived(int i, double v) : Base(i), val(v) {}
};C 遗留:typedef
C 中需要用 typedef 才能在声明变量时省略 struct 关键字。C++ 中不需要——直接写结构体名即可:
// C 风格(C++ 中仍合法但不必用)
typedef struct { int x, y; } Point_C;
// C++ 风格(推荐)
struct Point { int x, y; };
Point p{3, 4}; // C++ 中无需 struct 关键字模板 struct
template<typename T>
struct DataNode {
T value;
DataNode* next;
};
// 用法与 template class 完全等价实践
力扣题目:力扣去重排序(struct 封装计数),力扣排序(struct 成员排序),力扣堆(struct 作为 priority_queue 元素),力扣约瑟夫环(struct 链表节点)。
AI 自检:1) 给 AI 两个版本——一个用 struct 表示链表节点,一个用 class——要求解释它们在汇编层面的区别;2) 问 AI 在以下场景中应该选择 struct 还是 class:二维坐标点、RAII 文件句柄、线程安全队列、二叉树节点。
建议先阅读:05_面向对象(一)类与对象基础 — class 与 struct 的完整对比;06_面向对象(二)继承 — struct 同样支持继承体系。
C 语言关联:C 的 struct 是纯粹的字段聚合——无成员函数、无构造/析构、无访问控制、无继承。C++ 的 struct 是 class 的同义词。在需要与 C 交互的数据结构(如链表中传给 C 库的节点)上,建议保持 struct POD 特性以确保二进制兼容。详见 C 内存模型与布局 和 C 面向对象设计。