基本数据类型能够单独处理一些简单的单一数据。对于一些复杂的数据,需要用构造数据类型进行描述。构造数据类型是由用户按照一定的语法规则自定义的数据类型。C++语言支持的构造数据类型有数组,指针,引用,结构体,枚举和类等等。
数组是一系列具有相同类型的数据的集合。一维数组是存储相同类型的一组数据。数组的每个存储单元可存储一个数据,这些数据称为该数组的元素。每个元素都有一个标号,称为数组的下标。使用数组名和下标可以访问数组中的元素。以下是数组的定义语法:
<数据类型> <数组名>[<常量>] [={<初始值列表>}];
int a_array[5]; // 定义名称为a_array的数组,长度是5
a_array[0] = 1;
a_array[1] = 2;
a_array[2] = 3;
a_array[3] = 4;
a_array[4] = 5;
std::cout << a_array[1] << "\n"; // 输出 2
int b_array[5] = {1,2,3,4,5}; // 定义并初始化数组,能少,不能多
b_array[1] = 66;
std::cout << b_array[1] << "\n"; // 输出 66
数组的大小是一个常量,而不是一个变量,即数组大小是固定不变的明确数值。数组是内存中一片连续的存储空间,并固定下标从0开始计数,即第1个元素的下标是0,第2个元素的下标是1,以此类推。数组中任何一个元素都可以单独访问,访问的方式如下:<数组名>[<下标>]
备注:假如我们定义数组长度是10,但是访问的时候使用下标超过了10,例如x[12]去访问或者操作此元素,我们将这种情况称之为数组越界。越界访问数组可能导致程序出错,但是C++编译器对此并不做检查,但是程序运行的时候可能会崩溃!
多维数组是指维数大于1的数组,最常用的多维数组是二维和三维数组,定义如下方式:
int c_array[2][3]; // 定义一个2行3列的数组
c_array[0][0] = 1;
c_array[0][1] = 2;
c_array[0][2] = 3;
c_array[1][0] = 4;
c_array[1][1] = 5;
c_array[1][2] = 6;
std::cout << c_array[0][1] << "\n"; // 输出 2
int d_array[2][3] = { {1,2,3},{4,5,6} };
d_array[0][1] = 99;
std::cout << d_array[0][1] << "\n"; // 输出 99
二维数组可理解为“数组中的数组”,即数组中的每个元素又是一个一维数组。C++采用行优先存储规则,即先存第1行,再存第2行,以此类推。我们可以将一维数组理解成一行的线性数据形式,二维数组理解成行列的面性数据形式。例如上文中的c_array数组就如同这样的数据形式:
1 2 3
4 5 6
如果我们要访问二维数组里面的元素,就需要使用第一个中括号来确定第几行,然后使用第二个中括号来确定是第几列,这样就能唯一的标示出数组中的元素了。
按照数组元素的数据类型分类,数组可以分为数值数组,字符数组,指针数组,对象数组等等,这里重点介绍字符数组。字符数组是数据类型为char的数组。字符数组可以是一维的,用于存储一串字符,也可以是二维的,存储多个字符串。C++中的字符串在字符数组中以”\0”(ASCII码值为0的空字符)作为结束符。举例如下:
char e_array[3];
e_array[0] = 'a';
e_array[1] = 'b';
e_array[2] = 'c';
std::cout << e_array[1] << "\n"; // 输出 b
char f_array[3] = {'A','B','C'};
std::cout << f_array[1] << "\n"; // 输出 B
char g_array[] = "hello,array";
std::cout << g_array[1] << "\n"; // 输出 e
备注:用char数组存储字符串的时候,数组的长度为:西文字字符数加1,中文字符数乘2再加1。这是因为1个西方字符的编码占用1个字节,1个汉字字符的编码占2个字节,加1是用于存储”\0”空字符。如果使用wchar_t数组的话,数组长度计算就又不一样了,大家可以自行推测一下。
char g_array[] = "hello,array";
std::cout << g_array[1] << "\n"; // 输出 e
int g_len = sizeof(g_array) / sizeof(g_array[0]);
std::cout << g_len << "\n"; // 输出数组长度 12
char h_array[] = "中国";
int h_len = sizeof(h_array) / sizeof(h_array[0]);
std::cout << h_len << "\n"; // 输出数组长度 5
wchar_t w_array[] = L"中国";
int t_len = sizeof(w_array) / sizeof(w_array[0]);
std::cout << t_len << "\n"; // 输出数组长度 3
指针类型是C/C++语言特有的数据类型。其他高级语言(C#和Java)中,都不支持指针类型。指针是是一种特殊的数据类型,其值为内存地址。用指针类型说明的变量称为指针变量,保存了内存单元的地址。也就是说可以通过指针变量去直接访问内存空间。内存地址就是一个整数,系统为每个内存单元分配一个唯一的地址。定义指针变量的语法如下:
<数据类型> *<指针变量名> [= &<变量>];
int pa = 100; // 定义一个普通int变量p_a
int* pb = &pa; // 定义一个指针变量p_b,其值是变量p_a的内存地址
std::cout << *pb << "\n"; // 输出 100, pa和*pb 是同一个内存空间
*星号是指针类型的关键字。在定义指针变量的同时,可以把另一个变量的内存地址赋予给该指针变量。指针数据类型应该与后面变量的数据类型相同。指针变量可以赋值NULL或0,称之为空指针。用取地址符&可将普通变量的内存首地址赋值给指针变量。由于指针变量中存放的是内存首地址,因此指针变量的运算也就是内存地址的运算。
需要注意的是,在C++语言中,数组名就是一个指针常量,它指向数组的起始位置。也就是说,我们可以把数组名直接赋予一个指针变量,通过指针变量照样可以访问数组元素,如下:
int i_array[5] = { 1,2,3,4,5 };
int* pi = i_array; // 没有使用&取地址符
std::cout << *pi << std::endl; // 输出1,相当于i_array[0]
std::cout << *(pi+1) << std::endl; // 输出2,相当于i_array[1]
同样的,我们也可以使用指针来定义一个数组,如下:
int* p_array = new int[5]; // 用指针定义数组
p_array[0] = 123;
*(p_array + 1) = 456;
std::cout << p_array[0] << std::endl; // 输出123
std::cout << *(p_array+1) << std::endl; // 输出456
当使用一个指针变量指向一个二维数组的时候,指针变量对应的值就是一个一维数组,如下:
int j_array[2][3] = { {1,2,3},{4,5,6} }; // 定义一个二维数组
int(*pj)[3] = j_array; // 不能直接赋值给cPtr,得有[3]
std::cout << (*pj)[0] << std::endl; // 输出 1,相当于j_array[0][0]
std::cout << (*(pj+1))[0] << std::endl; // 输出 4,相当于j_array[1][0]
std::cout << *(*(pj+1)+1) << std::endl; // 输出 5,相当于j_array[1][1]
引用就是别名,就是给一个变量另命名一个名称。在程序中,可以用变量名访问变量的值,也可以用它的别名读取或操作变量的值。引用类型的定义语法如下:
<数据类型> &<引用变量名称> = <已定义的变量名>;
int rx = 200;
int& ry = rx; // 直接变量赋值即可
std::cout << ry << std::endl; // 输出 200,n就是m的另一个名字
&符号用于声明引用类型的关键字,<数据类型>必须与被引用变量的数据类型完全相同。引起变量只在定义时候赋值,之后引用变量不再接受另外变量名的赋值。请注意&符号的使用,在指针使用的时候,它作为操作符,用来获取变量的内存地址。在定义类型的时候,它表示引用数据类型。
int rz = 300;
ry = rz; // 按照理解,ry应该变了,指向了rz
std::cout << ry << std::endl; // 输出 300,这个ry是rx?还是rz?
rz = 400;
std::cout << ry << std::endl; // 输出 300,说明ry不是rz
std::cout << rz << std::endl; // 输出 400,说明ry不是rz
std::cout << rx << std::endl; // 输出 300,说明ry仍然是rx
我们再ry初始化的时候,指向了rx,说明ry就是rx。后面我们使用ry=rz的时候,并不是让ry指向rz,而是把300的数值给了ry和rx,这就是为什么rz变成400之后,ry和rx仍然是300。
结构体是一个由程序员自定义的数据类型,可以容纳许多不同的数据值。一旦结构体类型被声明并且其数据成员被标识,即可创建该类型的多个变量。
使用关键字 struct来声明结构体。举例如下:
struct Student // 定义一个学生的结构体
{
int num; // 学生序号
char* name; // 学生姓名
double score; // 学生考试分数
};
Student stu1;
stu1.num = 1;
stu1.name = (char*)"richie";
stu1.score = 100;
std::cout << stu1.name << std::endl; // 输出 richie
Student stu2 = { 2, (char*)"lee", 98 };
std::cout << stu2.name << std::endl; // 输出 lee
我们自定义了一个数据类型student,然后就可以将student当做一个数据类型使用,定义其变量。
枚举类型是由若干个语义相关的枚举常量组成的集合。定义语法如下:
enum color {red, green, blue}; // 定义 Color 枚举类型,其中red=0, green=1, blue=2
color eye = red; // 定于枚举型(color)变量eye,其值为red,也就是0
std::cout << eye << std::endl; // 输出 0
enum是枚举类型关键字,<枚举类型名>由用户自定义。一个枚举类型包含多个枚举常量。枚举类型定义后,<枚举类型名>即成为新的数据类型名称,与基本数据类型一样使用。我们使用color数据类型定义变量后,该变量的值就只能是定义color类型时候的red,green,blue三个数值中的一个。
本课程的所有代码案例下载地址:
C++示例源代码(配合教学课程使用)-C/C++文档类资源-CSDN下载
备注:这是我们游戏开发系列教程的第一个课程,主要是编程语言的基础学习,优先学习C++编程语言,然后进行C#语言,最后才是Java语言,紧接着就是使用C++和DirectX来介绍游戏开发中的一些基础理论知识。我们游戏开发系列教程的第二个课程是Unity游戏引擎的学习。课程中如果有一些错误的地方,请大家留言指正,感激不尽!
本文详细介绍了C++中的构造数据类型,包括数组、指针、引用、结构体和枚举等,阐述了它们的定义、使用方法及注意事项。

1375

被折叠的 条评论
为什么被折叠?



