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 链表节点)。