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_trivialis_standard_layout,可通过 <type_traits> 检查。
#include <type_traits>
static_assert(std::is_pod<Point>::value, "Point 必须是 POD");

8. 嵌套结构体与自引用

结构体内部可嵌套其它类型,若要定义自引用(指向自身类型),需借助指针或引用:

struct Node {
    int   value;
    Node* next;   // 指向同类型的指针
};

9. 常见用例

  1. 数据传输对象(DTO)/Plain-Old-Data:在网络、文件、共享内存等场景下,结构体清晰映射数据格式。
  2. 小型“类”:当所有成员均公开,且不需要封装、不需校验逻辑时,用 struct 更简洁。
  3. 联合体封装:结合标签(enum)与 union,实现节省内存的变体类型。

小结

  • C++ 中 struct 与 class 并无本质区别,唯独默认访问权限和继承权限不同。
  • 支持构造/析构、成员函数、继承、多态、模板等所有面向对象特性。
  • 聚合初始化和默认成员初始化让定义和使用更简洁。
  • 了解其内存布局、对齐规则,以及 POD/标准布局概念,可在性能和兼容性方面做更细致的优化。

类似文章

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注