本文系统讲解 C++ struct:基础语法与与 class 的差异、初始化与聚合、内存布局与对齐、位域、继承与多态可行性、与 C 的互操作、现代 C++ 特性、最佳实践与常见陷阱。包含可运行示例与构建指令。
目录
- 结构体基础与语法
struct与class的区别- 初始化与聚合(Aggregate)
- 内存布局与对齐(标准布局/POD)
- 位域(Bit-field)
- 继承与多态(可行性与影响)
- 与 C 的互操作
- 现代 C++ 特性要点
- 示例与构建
- 最佳实践与常见陷阱
结构体基础与语法
struct是用户自定义类型,和class本质相同,唯一区别是默认访问说明符与继承是public。- 成员可包括:数据成员、成员函数(含构造/析构)、静态成员、嵌套类型、类型别名。
- 作用域解析:
StructName::member;头文件声明、源文件实现可分离。
示例:
struct Point {
int x{0};
int y{0};
void move(int dx, int dy) { x += dx; y += dy; }
};
struct 与 class 的区别
- 默认访问:
struct默认public,class默认private;除此之外语义完全相同。 - 风格约定:常将
struct用于“纯数据载体”(POD/聚合)或轻量对象;class用于封装更强的类型与不变量。 - 访问控制:
struct也可显式使用private/protected,并具有构造、析构、虚函数、继承等能力。
初始化与聚合(Aggregate)
- 聚合类型:无用户自定义构造、无私有/受保护非静态成员、无虚函数、无基类等条件满足时,
struct为聚合。 - 聚合初始化:使用花括号按成员顺序初始化,支持 C++20 指定初始化(部分编译器支持有限)。
示例:
struct Color { int r; int g; int b; };
Color c1{255, 128, 64}; // 聚合初始化
内存布局与对齐(标准布局/POD)
- 标准布局(standard-layout):保证成员顺序与内存布局的可预期性,便于与 C 交互与序列化。
- POD(Plain Old Data):满足标准布局且平凡(trivial)的类型,支持 C 风格初始化与二进制拷贝。
- 对齐:类型有对齐要求(
alignof(T)),编译器可能插入填充字节(padding)。 - 观察布局:
sizeof(T)、offsetof(T, member)可用于了解大小与偏移。
示例:
#include
<cstddef>
struct alignas(16) Vec4 { float x,y,z,w; };
static_assert(alignof(Vec4) == 16);
static_assert(sizeof(Vec4) == 16);
size_t offx = offsetof(Vec4, x); // 0
位域(Bit-field)
- 位域允许以位级粒度定义成员宽度:
unsigned flags:3;。 - 注意事项:实现相关的布局与端序、跨平台差异、与
sizeof/offsetof的交互;常用于嵌入式或协议头。
示例:
struct Header {
unsigned version:4;
unsigned type:4;
unsigned length:16;
};
继承与多态(可行性与影响)
struct可继承与定义虚函数,多态能力与class一致;含虚函数会引入虚表指针影响布局。- 默认继承是
public:struct Derived : Base {};当作接口也需虚析构。
示例:
struct Shape { virtual ~Shape() = default; virtual double area() const = 0; };
struct Rect : Shape { double w{}, h{}; double area() const override { return w*h; } };
与 C 的互操作
- 与 C 接口互通通常需要标准布局且避免 C++ 特性(虚函数、非平凡构造/析构)。
- 使用
extern "C"暴露函数名以避免名称修饰;结构体作为数据交换需保证 ABI 兼容。 - 谨慎使用
#pragma pack修改对齐;更建议用alignas与静态断言校验大小。
示例:
extern "C" {
struct CPoint { int x; int y; };
void process_point(struct CPoint* p); // C 风格接口
}
static_assert(std::is_standard_layout
<CPoint>::value, "must be standard layout");
现代 C++ 特性要点
=default/=delete:控制特殊成员函数的生成或禁用。constexpr/consteval:编译期常量与编译期计算的结构体方法/构造。[[nodiscard]]:防止忽略关键返回值;noexcept:强异常安全保证与优化提示。- 规则(Three/Five/Zero):资源管理最好交由标准容器/智能指针,结构体保持聚合风格。
示例:
struct Config {
int port{};
[[nodiscard]] bool valid() const noexcept { return port > 0; }
};
示例与构建
struct_demo.cpp
#include
<iostream>
#include
<cstddef>
#include
<type_traits>
struct Color { int r; int g; int b; };
struct alignas(16) Vec4 { float x,y,z,w; };
struct Header { unsigned version:4; unsigned type:4; unsigned length:16; };
int main() {
Color c{255,128,64};
std::cout << c.r << "," << c.g << "," << c.b << "\n";
Vec4 v{1,2,3,4};
std::cout << "alignof(Vec4)=" << alignof(Vec4) << ", sizeof(Vec4)=" << sizeof(Vec4) << "\n";
std::cout << "offsetof(Vec4::x)=" << offsetof(Vec4, x) << "\n";
Header h{1,2,100};
std::cout << "version=" << h.version << ", type=" << h.type << ", length=" << h.length << "\n";
static_assert(std::is_standard_layout
<Color>::value);
return 0;
}
构建与运行(macOS zsh):
clang++ -std=gnu++20 struct_demo.cpp -o struct_demo
./struct_demo
最佳实践与常见陷阱
- 用于数据载体时保持聚合特性,避免引入虚函数/私有成员导致失去聚合初始化。
- 注意填充与对齐,序列化/与 C 交互前用
static_assert(sizeof(T)==预期)验证。 - 位域跨平台差异显著;协议头尽量使用显式字节序与序列化函数,不直接依赖位域布局。
- 初始化顺序与成员声明顺序一致;避免未初始化成员。
- 与 C 接口交互时避免使用异常、模板、复杂构造;保持标准布局与平凡性。
正文完


