C++ 结构体(struct)
在 C++ 中,struct
(结构体)是一种用户自定义的复合数据类型,用来将多个不同类型的变量组合在一起。它与 class
的唯一区别在于默认的成员访问权限和继承权限。下面分几个方面介绍它的用法与特性。
1. 基本定义与访问权限
// 定义一个表示二维点的结构体
struct Point {
double x; // 公有成员
double y; // 公有成员
};
- 默认成员访问权限:
struct
的成员默认是 public;而class
默认是 private。 - 也可以显式指定访问权限:
struct Person { private: std::string name; int age; public: void setName(const std::string& s) { name = s; } std::string getName() const { return name; } void setAge(int a) { age = a; } int getAge() const { return age; } };
2. 初始化 — 聚合初始化 (Aggregate Initialization)
C++11 起,结构体可通过花括号列表直接初始化成员(聚合初始化):
Point p1 { 3.0, 4.0 }; // x=3.0, y=4.0
Point p2 = { 1.0, 2.0 }; // 等价写法
struct RGB { int r, g, b; };
RGB color { 255, 128, 0 };
- 若有默认成员(C++11 支持默认成员初始化),后续成员可省略:
struct Config { int width = 800; int height = 600; bool fullscreen = false; }; Config cfg { 1024 }; // width=1024, height=600, fullscreen=false
3. 方法与构造函数
结构体可以拥有构造函数、析构函数、成员函数、静态成员、访问控制等:
struct Rectangle {
double width, height;
// 构造函数
Rectangle(double w, double h) : width(w), height(h) {}
// 成员函数
double area() const {
return width * height;
}
};
// 使用
Rectangle rect{ 5.0, 2.0 };
std::cout << "面积: " << rect.area() << "\n";
- C++11 也支持
constexpr
构造函数,用于编译期常量:struct Vec3 { double x, y, z; constexpr Vec3(double a, double b, double c) : x(a), y(b), z(c) {} }; constexpr Vec3 unitX{1,0,0};
4. 继承与多态
struct
同样支持继承与多态,只是默认继承是 public:
struct Base {
virtual void f() { std::cout << "Base\n"; }
};
struct Derived : Base { // public 继承
void f() override { std::cout << "Derived\n"; }
};
Base* b = new Derived();
b->f(); // 调用 Derived::f()
5. 匿名结构体与联合体
- 匿名结构体:在另一个结构体内定义、不起名,可直接访问其成员(少用,阅读性差)。
- 联合体 (
union
):不同成员共用同一块内存,可与struct
组合实现节省空间的 标签联合(tagged union)。
struct Variant {
enum { INT, DOUBLE } type;
union {
int i;
double d;
};
};
Variant v;
v.type = Variant::DOUBLE;
v.d = 3.14;
6. 内存布局与对齐
- 成员按声明顺序排列,编译器会根据对齐规则插入填充字节。
- 可用
#pragma pack
或属性(attribute)改变对齐,但会影响性能和可移植性,一般慎用。
#pragma pack(push,1)
struct Packed {
char c;
int i;
};
#pragma pack(pop)
// sizeof(Packed) 现在可能是 5 而不是默认的 8
7. POD、标准布局与平凡类型
- POD(Plain Old Data):平凡且标准布局的类型,可与 C 兼容。
- C++11 起对概念细分为
is_trivial
、is_standard_layout
,可通过<type_traits>
检查。
#include <type_traits>
static_assert(std::is_pod<Point>::value, "Point 必须是 POD");
8. 嵌套结构体与自引用
结构体内部可嵌套其它类型,若要定义自引用(指向自身类型),需借助指针或引用:
struct Node {
int value;
Node* next; // 指向同类型的指针
};
9. 常见用例
- 数据传输对象(DTO)/Plain-Old-Data:在网络、文件、共享内存等场景下,结构体清晰映射数据格式。
- 小型“类”:当所有成员均公开,且不需要封装、不需校验逻辑时,用
struct
更简洁。 - 联合体封装:结合标签(enum)与
union
,实现节省内存的变体类型。
小结
- C++ 中
struct
与class
并无本质区别,唯独默认访问权限和继承权限不同。 - 支持构造/析构、成员函数、继承、多态、模板等所有面向对象特性。
- 聚合初始化和默认成员初始化让定义和使用更简洁。
- 了解其内存布局、对齐规则,以及 POD/标准布局概念,可在性能和兼容性方面做更细致的优化。