数组

数组是具有一定顺序关系的对象集合,构成数组的对象成为该数组的元素。数组名称是一个不能被赋值的指针,称为指针常量。

C++中的二维数组被视为一维数组的数组。因此,二维数组以行优先的顺序存储。


在作为参数传递数组时,通常不指定第一维的大小,即使指定也会被忽略。

程序示例—线性拟合

查看源代码


指针

基本定义和用法省略。

void指针的使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <iostream>
using namespace std;

int main(){
void voidObject; //不能声明void类型的变量
void *pv; //可以声明void类型的指针
int i = 5;
pv = &i;
int *pint = static_cast<int *>(pv);
cout << "* pint=" << * pint << endl;
return 0;
}

运行结果:
* pint = 5

当指针指向的数据类型不确定时,通常只使用void指针。

空指针的使用

不同类型的指针之间或指针与非零整数之间的算术运算是无意义的,但指针变量可以与整数0进行比较。0专门用来表示空指针,即不指向任何有效地址的指针。

空指针也可以使用NULL表示。

NULL是许多头文件中定义的宏,定义为0。

对象指针

顾名思义,指向对象的指针。

使用对象指针时,对象成员可以非常直观地表示。语法形式为object_pointer_name->member_name,相当于访问(*object_pointer_name).member_name

在类的组合中,有一个概念叫做前向引用声明,其中两个类在定义时相互引用。这个问题可以通过使用指针来解决。

1
2
3
4
5
6
7
class A;         //前向引用声明
class B{
A *x;
};
class A{
B *y;
}

声明指针而不是对象是允许的。一旦A被定义,就可以声明A对象。

this指针

this指针是每个类的非静态成员函数(包括构造函数和析构函数)中隐式存在的特殊指针,用于指向被成员函数操作的对象

this指针是成员函数的隐式参数,使得函数能够知道它正在操作哪个对象,从而访问其数据成员。对于常量成员函数,这个隐式参数是常量指针类型。

指向类的非静态成员的指针

声明语句:

1
2
type_specifier class_name::* pointer_name                           //声明指向数据成员的指针
type_specifier (class_name::* pointer_name)(parameter_list); //声明指向函数成员的指针

为数据成员的指针赋值的一般语法为:

1
pointer_name = &class_name::data_member_name;

访问数据成员时,可以使用:

1
2
3
object_name.*class_member_pointer_name

object_pointer_name -> *class_member_pointer_name

为成员函数的指针赋值的一般语法为:

1
pointer_name = &class_name::function_member_name;

指向类的静态成员的指针

只需使用普通指针:

1
2
type_specifier  *pointer_name = &class_name::static_data_member
type_specifier (*pointer_name)(formal_parameters) = &class_name::static_member_function

动态内存分配

在C++程序中,使用两个运算符来创建和删除堆对象(在程序执行期间申请和释放的存储单元):newdelete

有new的地方,必须有delete来释放,否则会导致无法回收内存,造成程序占用越来越多的内存,称为内存泄漏。

创建类的对象

使用new创建类对象时需要注意的细节。

如果类有用户定义的默认构造函数,则new Tnew T()没有区别。

如果类没有定义默认构造函数,使用new T将调用系统生成的隐式默认构造函数;使用new T()除了执行这个隐式函数外,还会将基本数据类型和指针类型的成员初始化为0,并且这个过程是递归的。

创建多维数组

形式如下:

1
new type_name T[array_first_dimension_length][array_second_dimension_length]...;

数组的第一维长度可以是任何表达式,结果为正整数,而其他数组维度的长度必须是常量表达式,结果为正整数。

错误示例:

1
2
float * fp;
fp = new float[10][25][10]

这里的new操作产生一个指向$25 \times 10$二维浮点类型数组的指针,而fp是指向浮点类型数据的指针,造成矛盾!

使用vector创建数组对象

C++提供了一种封装的动态数组—vector,具有多种类型。vector不是一个类,而是一个类模板

使用vector定义动态数组的形式为:

1
vector<element_type> array_object_name(array_length);

由vector定义的数组对象的所有元素都会被初始化。如果它们是基本数据类型,所有元素将被初始化为0;如果它们是类类型,将调用类的默认构造函数进行初始化。因此,必须确保作为数组元素使用的类需要有默认构造函数。可以指定初始值,但所有元素的初始值必须相同

引用相关补充

引用通常用于函数参数列表和函数返回值。以下是与C++引用相关的两个重要概念,C++程序员必须理解:

使用引用作为参数

使用引用作为返回值

深拷贝与浅拷贝

隐式拷贝构造函数仅实现浅拷贝,但这种拷贝并不适用于所有情况。

浅拷贝代码示例

深拷贝代码示例

字符串

C++封装了一系列复杂的字符串操作,形成了字符串类,以便更方便地进行字符串操作。

许多字符串操作需要借助cstring头文件中的字符串处理函数。使用字符串类需要包含string头文件。

字符串相关说明

个人银行账户管理程序

对之前管理程序的功能补充。

GitHub上的源代码