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); }
};
```cpp
### 底层等价性
编译器对 struct 和 class 生成的汇编代码**完全相同**。以下两段代码产生的机器码一致:
```cpp
struct S { int x; void f() { x = 1; } };
class C { public: int x; void f() { x = 1; } };
```cpp
这印证了一个关键事实:C++ 的访问控制(public/private)是纯编译期的概念——在运行时和汇编层面不存在任何区别或开销。
### struct 内存布局
与 class 完全一致:成员按声明顺序排列;对齐规则相同(当前偏移须被成员类型大小整除);同样支持虚函数(引入 vptr 于偏移 0 处)。
```cpp
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)
```cpp
### 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 函数。
---
## 语法
### 聚合初始化
```cpp
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 指定初始化器
```cpp
### struct 与数据结构
struct 是构建所有数据结构的基石节点:
```cpp
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; };
```cpp
### struct 的构造/析构/继承
struct 可以拥有与 class 完全相同的构造体系:
```cpp
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) {}
};
```cpp
### C 遗留:typedef
C 中需要用 `typedef` 才能在声明变量时省略 `struct` 关键字。C++ 中不需要——直接写结构体名即可:
```cpp
// C 风格(C++ 中仍合法但不必用)
typedef struct { int x, y; } Point_C;
// C++ 风格(推荐)
struct Point { int x, y; };
Point p{3, 4}; // C++ 中无需 struct 关键字
```cpp
### 模板 struct
```cpp
template<typename T>
struct DataNode {
T value;
DataNode* next;
};
// 用法与 template class 完全等价
```cpp
---
## 实践
**练习**:去重排序题(struct 封装计数),排序题(struct 成员排序),堆题(struct 作为 priority_queue 元素),约瑟夫环题(struct 链表节点)。