CPP数组、指针和字符串
数组
数组是具有一定顺序关系的若干对象的集合体,组成数组的对象成为该数组的元素。数组名是一个不能被赋值的指针,叫做指针常量。
C++中的二维数组被当作一维数组的数组。因此二维数组是按照行优先的顺序存储。
把数组作为参数时,一般不指定数组第一维的大小,即使指定,也会被忽略。
程序实例—线性拟合
指针
基本定义使用略去。
void指针的使用
1 |
|
void指针一般只在指针所指向的数据类型不确定的时候使用。
空指针的使用
不同类型的指针之间或者指针与非零整数之间的关系运算是毫无意义的,但是指针变量可以和整数0进行比较。0专用于表示空指针,也就是一个不指向任何有效地址的指针。
空指针同时也可以用NULL表示。
NULL是一个在很多头文件中都有定义的宏,该定义为0。
对象指针
顾名思义,指向一个对象的指针。
使用对象指针时,可以很形象的表示对象的成员,语法形式为对象指针名->成员名
这个与(*对象指针名).成员名
的访问是等价的。
前面在类的组合时有个知识点叫做前向引用声明,当时有两个类,在定义时互相引用,这个问题就可以用指针解决。
1 | class A; //前向引用说明 |
声明一个指针而不是对象时允许的,当A定义完,就可以声明A对象。
this指针
this指针是一个隐含于每一个类的非静态成员函数中的特殊指针(包括构造函数和析构函数),它用于指向正在被成员函数操作的对象
this指针是成员函数的隐含参数,让函数知道操作的是哪个对象,从而访问其数据成员。对于常成员函数来说,这个隐含的参数是长指针类型的。
指向类的非静态成员的指针
声明语句
1 | 类型说明符 类名::* 指针名 //声明指向数据成员的指针 |
为指向数据成员的指针赋值的一般语法形式为
1 | 指针名 = &类名::数据成员名; |
访问数据成员时,可以
1 | 对象名.*类成员指针名 |
为指向成员函数的指针赋值的一般语法为
1 | 指针名 = &类名::函数成员名; |
指向类的静态成员的指针
只需要使用普通的指针就可以
1 | 类型说明符 *指针名 = &类名::静态数据成员 |
动态内存分配
在C++程序中建立和删除堆对象(程序运行过程中申请和释放的存储单元)使用的两个运算符:new
和delete
。
有new必有delete释放,否则导致无法回收内存,使得程序占据的内存越来越大,叫做内存泄漏。
创建一个类的对象
new建立一个类的对象时,需要注意的细节。
如果该类存在用户定义的默认构造函数,那么
new T
和new T()
没有任何的区别。如果该类没有定义默认的构造函数,使用
new T
时会调用系统生成的隐含的默认构造函数;使用new T()
时,除了执行这个隐含的函数,还会为基本数据类型和指针类型的成员用0赋初值,这一过程是递归的。
创建多维数组
形式如下:
1 | new 类型名T[数组第1维长度][数组第二维长度]...; |
其中数组的第一维长度可以是任何结果为正整数的表达式,而其他各维数组的长度必须是结果为正整数的常量表达式。
错误的例子:
1 | float * fp; |
在这里new操作产生的是一个指向一个$25 \times 10$
的二维float类型数组的指针,而fp是一个指向float型数据的指针,产生了矛盾!
用vector创建数组对象
C++提供了被封装的动态数组—vector,具有各种类型。vector不是一个类,而是一个类模板。
使用vector定义动态数组的形式为:
1 | vector<元素类型>数组对象名(数组长度); |
vector定义的数组对象的所有元素都会被初始化。如果为基本数据类型,则所有元素都会被0以初始化;如果为类类型,则会调用类的默认构造函数初始化。所以需要保证作为数组元素的类需要具有默认构造函数,初值可以指定,但是所有的元素初值必须是一样的。
引用相关补充
引用通常用于函数参数列表和函数返回值。下面列出了 C++ 程序员必须清楚的两个与 C++ 引用相关的重要概念:
深复制与浅复制
隐含的复制构造函数实现的只是浅复制,但是这样的复制并不适用于所有的情况。
字符串
C++对字符串一系列复杂的操作进行了封装,形成了string类,更加方便的操作字符串。
执行很多字符串操作需要借助cstring头文件中的字符串处理函数,使用string类需要包含头文件string。
个人银行账户管理程序
对于上一个管理程序的功能补充。