C++ 结构体:struct 的定义与结构体数组

C++ 中 struct(结构体)的定义与结构体数组 是 C++ 基础中非常重要且经常在面试、笔试、算法题中出现的知识点。

下面从定义方式内存对齐初始化结构体数组常见用法注意事项面试高频问题 全面讲解。

1. struct 的基本定义

C++ 中的 struct 与 C 语言基本一致,但功能更强大(可以包含成员函数、访问控制等)。

// 最基本写法
struct Student {
    int id;           // 学号
    std::string name; // 姓名
    int age;          // 年龄
    double score;     // 分数
};

// 带默认访问权限(public)
struct Point {
    double x;
    double y;
    double z;
};

C++ 中 struct 和 class 的主要区别(面试常考):

  • 默认访问权限不同:
  • struct 默认是 public
  • class 默认是 private
  • 其他(继承、构造、析构等)几乎无区别

现代 C++ 推荐
如果只是数据载体(POD 类型),用 struct
如果有行为(成员函数较多、封装),用 class

2. 结构体的初始化方式(多种写法)

#include <string>

struct Student {
    int id;
    std::string name;
    int age;
    double score;
};

// 方式1:C风格初始化(最常见)
Student s1 = {1001, "Alice", 20, 95.5};

// 方式2:C++11 列表初始化(推荐)
Student s2{1002, "Bob", 21, 88.0};

// 方式3:指定成员初始化(C++20 更友好)
Student s3{.id = 1003, .name = "Charlie", .age = 19, .score = 92.5};

// 方式4:默认构造 + 逐个赋值
Student s4;
s4.id = 1004;
s4.name = "David";
s4.age = 22;
s4.score = 85.0;

3. 结构体数组(最常考)

// 定义结构体数组
Student students[5];                    // 5 个元素,默认构造

// 初始化结构体数组
Student class1[3] = {
    {1001, "Alice", 20, 95.5},
    {1002, "Bob",   21, 88.0},
    {1003, "Carol", 19, 92.5}
};

// C++11 统一初始化
Student class2[] = {
    {1004, "David",  20, 90.0},
    {1005, "Eve",    21, 85.5},
    {1006, "Frank",  22, 93.0}
};

// 现代写法(推荐)
Student class3[4]{
    {.id=1007, .name="Grace", .age=20, .score=96.0},
    {.id=1008, .name="Henry", .age=19, .score=89.5},
    {.id=1009, .name="Ivy",   .age=21, .score=91.0},
    {.id=1010, .name="Jack",  .age=20, .score=87.0}
};

遍历方式对比

// 传统 for
for(int i = 0; i < 3; i++) {
    std::cout << class1[i].name << " " << class1[i].score << "\n";
}

// 范围 for(C++11+,推荐)
for(const auto& stu : class1) {
    std::cout << stu.name << " " << stu.score << "\n";
}

4. 结构体内存对齐(面试高频)

C++ 会对结构体成员进行内存对齐(padding),目的是提高访问效率。

默认对齐规则(大多数编译器):

  • 每个成员的起始地址必须是自身大小系统默认对齐数的整数倍
  • 整个结构体的大小必须是最大成员对齐数的整数倍
struct A {
    char a;     // 1 字节
    int b;      // 4 字节
    double c;   // 8 字节
};

// 实际占用:24 字节(不是 1+4+8=13)

内存布局(64位系统,典型 8 字节对齐):

偏移 0:   char a          (1字节 + 3字节填充)
偏移 4:   int b           (4字节)
偏移 8:   double c        (8字节)
总大小:24 字节

控制对齐方式(常用技巧):

// 方法1:使用 #pragma pack
#pragma pack(1)     // 1 字节对齐(取消填充)
struct B {
    char a;
    int b;
    double c;
};                  // 大小 13 字节
#pragma pack()      // 恢复默认

// 方法2:C++11 alignas
struct alignas(16) Vec4 {
    float x, y, z, w;
};

5. 结构体数组的典型应用场景(算法题常见)

// 例:按分数降序排序
bool cmp(const Student& a, const Student& b) {
    return a.score > b.score;
}

std::sort(std::begin(students), std::end(students), cmp);

// 例:结构体数组 + 结构体指针
Student* p = students;
p[0].score += 10;       // 等价于 students[0].score += 10

6. 面试高频问题汇总

问题核心回答要点
struct 和 class 区别?默认访问权限不同(public vs private),其他几乎相同
结构体可以有成员函数吗?可以(C++ 支持),甚至可以有构造函数、析构函数、static 成员
结构体数组名是什么?指向首元素的指针(退化为指针),但不能直接 ++ / 赋值
结构体作为函数参数,传值还是传引用?推荐传 const 引用(避免拷贝开销)
结构体内存对齐为什么存在?提高 CPU 访问效率(对齐访问快于非对齐访问)
怎么让结构体按 1 字节对齐?#pragma pack(1)alignas(1)
结构体可以作为 STL 容器元素吗?可以,但要满足可拷贝构造可赋值(现代 C++ 更推荐 move 语义)
结构体数组和指针数组哪个更常用?看场景:连续存储用结构体数组,动态大小用指针数组(vector)

7. 小结口诀(快速记忆)

  • struct 默认 public,class 默认 private
  • 结构体数组名 → 首元素地址
  • 内存对齐 → 看最大成员 + 编译器默认
  • 初始化 → {} 列表初始化最现代
  • 排序/查找 → 配合 std::sortstd::lower_bound 使用
  • 传参 → 优先 const Student& 避免拷贝

如果你当前在准备面试或刷题,想针对结构体 + 链表/树/排序/哈希 的经典题目,我可以继续给你出题或讲解典型代码(比如结构体表示链表节点、坐标点排序、学生信息管理等)。

需要哪一部分再深入?直接说!

文章已创建 4631

发表回复

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

相关文章

开始在上面输入您的搜索词,然后按回车进行搜索。按ESC取消。

返回顶部