结构与值类型

单个 int 或 double 表达不了“一个位置”这种成组出现的数据。struct 把几个相关的值收进一个类型,实例之间按值复制、互不影响。本章建立聚合与值语义的心智模型,成员函数和访问控制留给后面的自定义类型章节。

组合数据

struct 逐个声明成员并给出默认值,完整示例表达棋盘上的两个位置:

structs-and-value-types.cpp
// 结构体与值类型示例:用 struct 聚合坐标成员并逐个输出。
#include <iostream>

struct Position {
  int x{0};
  int y{0};
};

int main() {
  Position start{1, 2};
  Position finish{2, 2};
  std::cout << "起点: " << start.x << "," << start.y << "\n";
  std::cout << "终点: " << finish.x << "," << finish.y << "\n";
  return 0;
}

Position start{1, 2}; 按成员声明顺序初始化 x 和 y,省略的成员使用默认值,例如 Position corner{2}; 的 y 是 0。访问成员用 .,例如 start.x。

复制的是值

片段:复制后的两个独立对象
// 片段
Position a{1, 2};
Position b = a;  // 复制 a 的全部成员
b.x = 9;         // 只修改 b
// a.x 仍是 1

把结构体赋给新变量会复制全部成员的值,修改其中一个不影响另一个,这是值类型的行为。想让两个名字指向同一份数据,需要引用或指针,选型方式见下一章引用使用场景。

常见错误

初始化值顺序错

聚合初始化按声明顺序对应成员,{1, 2} 与 {2, 1} 是两个不同位置,成员多时在初始化旁注释各值,或拆成更小的类型。

以为复制共享成员

结构体变量各自持有独立的成员值,把“复制后还联动”的期待留给引用与指针章节处理。

自测问题

  1. Position p{2}; 之后 p.y 是什么?

    查看答案

    是 0:初始化列表只提供 x 的值,y 使用成员声明里的默认值。

  2. 把 a 赋给 b 之后修改 b.x,a.x 会跟着变吗?

    查看答案

    不会。赋值复制了全部成员,两个对象互不影响,这是值类型的语义。

  3. 什么时候应该把数据组合成 struct?

    查看答案

    几个值总是作为整体出现、一起传递和比较时,例如位置由横纵坐标组成。单个值能表达清楚时不强行包装。

本章回顾

你现在能用 struct 聚合相关的数据并理解按值复制的独立性。完整示例见 structs-and-value-types.cpp。