CPP-05-结构

结构体

结构是一种比数组更灵活的数据格式,一个结构可以存储多种类型的数据

1
2
3
4
5
6
struct inflatable
{
char name[20];
float volume;
double price;
};

定义之后就可以使用结构体声明变量,与C不同的是,C++允许在声 明结构变量时省略关键字struct

1
2
inflatable hat;					//ok
struct inflatable mainframe; //ok

与数组一样,C++11也支持将列表初始化用于结构,且等号 = 是可选的

1
2
3
4
5
6
7
8
9
10
11
inflatable guest =
{
"Glorious Gloria",
1.88,
29.99
};
inflatable local = {"Audacious Arthur", 3.12};
inflatable other{};
//cout << guest << endl; //没有与这种操作相匹配的 << 运算符
cout << other.name << endl;
cout << local.price << endl;

运行结果

1
2

0

所以

  1. = 是可选的
  2. 如果为设置值的情况下,默认为0值

同理在复制过程中,结构体也是值复制

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
inflatable guest =
{
"Glorious Gloria",
1.88,
29.99
};

inflatable other{};
other = guest;
//other.name = "hello wrold"; //表达式必须是可修改的左值
strcpy_s(other.name, sizeof(other.name) - 1, guest.name);
other.price = 1.2;

cout << other.price<< endl;
cout << guest.price<< endl;

运行结果

1
2
1.2
2.99
  1. 结构体的复制也是值复制,修改并不会影响另外一个结构体对象
  2. 为什么使用 strcpy_s 而不是使用 strncpy 或者 strcpy,可以参考 https://www.yuankang.top/2023/07/28/C++/CPP-04-string类/ 中的说明

结构体变量还有其他创建方式

  1. 声明两个结构体变量

    1
    2
    3
    4
    5
    6
    struct inflatable
    {
    char name[20];
    float volume;
    double price;
    } infla1, infla2; //声明两个结构体变量
  2. 直接初始化结构体变量

    1
    2
    3
    4
    5
    6
    7
    8
    9
    struct perks
    {
    int key_number;
    char car[12];
    } per =
    {
    7,
    "Packard"
    };
  3. 声明结构体变量(无法重复声明一样结构体变量,不建议使用)

    1
    2
    3
    4
    5
    struct	// no tag
    {
    int x; //2 member
    int y;
    } position; //a structure variable

共用体

共用体(union)是一种数据格式,它能够存储不同的数据类型, 但只能同时存储其中的一种类型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
union one4all
{
int int_val;
long long_val;
double double_val;
};

one4all pail = {};
pail.bool_val = true;
cout << pail.bool_val << endl;
cout << pail.int_val << endl;
cout << pail.double_val << endl;
pail.double_val = 1.1;
cout << pail.bool_val << endl;
cout << pail.int_val << endl;
cout << pail.double_val << endl;

运行结果

1
2
3
4
5
6
1
1
4.94066e-324
0
-1717986918
1.1

从运行结果可以看出

  1. 未设置共用体情况下,共用体的字段值是未知的
  2. 当设置一个字段的情况下,另外一个字段将失效

由于共用体每次只能存储一个值,因此它必须 有足够的空间来存储最大的成员,所以,共用体的长度为其最大成员的 长度

将结构体与共用体结合

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
struct widget
{
char brand[20];
int type;
union id
{
long id_num;
char id_char[20];
} id_val;
};

widget prize;
if(prize.type == 1)
cin >> prize.id_val.id_num;
else
cin >> prize.id_val.id_char;

可以通过匿名共用体的方式减少名称调用,其成员将成为相同地址处的变量。每次只有一个成员是当前的成员

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
struct widget
{
char brand[20];
int type;
union
{
long id_num;
char id_char[20];
};
};

widget prize;
if(prize.type == 1)
cin >> prize.id_num;
else
cin >> prize.id_char;

共用体常用于(但并非只能用于)节省内存

枚举

C++的enum提供了另一种创建符号常量的方式,这种方式可以代替const,使用 enum的句法与使用结构相似

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
enum spectrum
{
red,
orange,
yellow,
greed,
blue
};

spectrum band;
band = yellow;
cout << band << endl;
//band = 2000; //不能将 "int" 类型的值分配到 "spectrum" 类型的实体
band = spectrum(1);
cout << band << " "<< (band == orange) << endl;

输出结果

1
2
2
1 1
  1. enum 可以直接通过枚举序号获取 band = spectrum(1);
  2. 枚举类型可以比较默认从 0 开始

更进一步,可以为枚举设置值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
enum spectrum
{
red = 9,
orange = 10,
yellow = 100,
greed = 4,
blue = 5
};

spectrum band;
band = red;
cout << band << endl;
band = spectrum(99);
cout << band << " "<< (band == orange) << endl;

输出结果

1
2
9
99 0
  1. 可以直接使用 spectrum(99) 声明一个新的枚举类型值
  2. 枚举类型设置的值并没有顺序要求
  3. 枚举值的最大值 = 枚举量的最大值。找到大于这个最大值的、最小的2的幂,将它减去1,得到的便是取 值范围的上限。

既能顺便设置值,又能不设置值,name

1
2
3
4
5
6
7
8
9
10
11
enum spectrum
{
red,
orange = 0,
yellow = 1,
greed = 1,
blue
};

cout << (red == orange) << (orange == yellow) << endl;
cout << red << orange << yellow << greed << blue << endl;

输出结果

1
2
10
00112
  1. 默认是从 0 开始的
  2. 枚举可以设置成相同的值

参考链接

  1. 《C++ Primer Plus》