结构体数组声明需先定义类型再声明数组,如struct Point{int x,y;};Point points[5];支持初始化Point points[3]={{1,2},{3,4},{5,6}};访问用points[0].x;传参时数组退化为指针,须显式传长度。

结构体数组声明和初始化要配对类型
声明结构体数组时,必须先定义结构体类型,再用该类型声明数组。常见错误是把结构体定义和数组声明写反,或者漏掉数组大小导致编译失败。
- 正确写法:
struct Point { int x; int y; };<br>Point points[5]; // 声明含5个Point的数组 - 支持初始化:
Point points[3] = {{1,2}, {3,4}, {5,6}}; - 若用
std::vector替代原生数组,需写std::vector,不能写std::vector(C++ 中struct标签在类型名后不参与声明) - 零初始化可用
Point arr[3]{};(C++11 起),会将每个成员设为 0;但Point arr[3];不初始化,值是未定义的
访问结构体数组元素要用方括号加点号
数组下标访问返回的是单个结构体对象,之后才能用点号访问其成员。容易错写成连写点号或误用箭头(->)——那是给指针用的。
- 正确:
points[0].x = 10;<br>std::cout
- 错误:
points.x[0](语法非法)、points[0]->x(points[0]是对象,不是指针) - 若持有指针(如
Point* p = points;),才用p[0].x或(p+1)->y;但直接用数组名更清晰
传参给函数时注意数组退化问题
C++ 原生数组作为函数参数会退化为指针,丢失长度信息。结构体数组也不例外,func(Point arr[]) 实际等价于 func(Point* arr)。
- 推荐显式传入长度:
void printPoints(Point arr[], int size) {<br> for (int i = 0; i std::cout }<br>} - 更安全的做法是用
std::array或std::vector,它们携带大小且可按值传递 - 若坚持用原生数组,可用模板推导大小:
template<size_t n><br>void process(const Point (&arr)[N]) { /* N 可用 */ }</size_t>
结构体含非POD成员时数组初始化要小心
如果结构体里有 std::string、std::vector 等非平凡类型,原生数组仍可声明,但不能用 {} 进行聚合初始化(C++11 后部分放宽,但仍有约束)。
- 例如:
struct Person { std::string name; int age; };<br>Person people[2] = {{"Alice", 30}, {"Bob", 25}}; // OK(C++11 起支持) - 但若结构体含默认构造被删除的成员,或含引用成员,则无法定义数组(编译报错)
- 运行时动态分配结构体数组(如
new Person[3])会调用每个元素的默认构造函数;若无默认构造函数,会编译失败 - 释放时必须用
delete[] ptr;,不能只写delete ptr;,否则未定义行为
实际用的时候,多数场景建议优先用 std::vector;只有对内存布局、缓存友好性或嵌入式环境有硬性要求时,才选原生结构体数组。后者一旦涉及拷贝、扩容、生命周期管理,就很容易踩到隐式规则的坑。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











