前言
指针是C++从C中继承过来的重要数据类型,提供了一种较为直接的地址操作手段。正确地使用指针,可以方便、灵活而有效地阻止和表示复杂的数据结构。动态内存分配和管理也离不开指针。
一、指针变量的声明
指针也是一种数据结构,具有指针类型的变量。指针变量适用于存放内存单元地址的。指针也是先声明后使用的,声明指针的语法形式为: 数据类型 *标识符; 如下所示:
int *p;
二、与地址相关的运算
C++提供了两个与地址相关的运算符——*和&。*称为指针运算符,也成为解析,表示获取指针所指向的变量的值,这是一个一元操作符。&称为取地址运算符,也是一个一元操作符,用来得到一个对象的地址。 注:*和&出现在声明语句中和执行语句中其含义是不同的,它们作为一元运算符和作为二元运算符时其含义也是不同的。 *出现在声明语句中,在被声明的变量名之前时,表示声明的是指针;出现在执行语句中或声明语句的初始化表达式中作为一元运算符时,表示访问指针所指对象的内容。 &出现在变量声明语句中位于被声明的变量左边时,表示声明的是引用;在给变量赋初值时出现在等号右边或在执行语句中作为一元运算符出现时,表示取对象的地址。
三、指针的赋值
对指针的赋值有两种方法: 1)在定义指针的同时进行初始化赋值。语法形式如下: 存储类型 数据类型 *指针名=初始地址; 2)在定义之后,单独使用赋值语句。赋值语句的语法形式如下: 指针名 地址 注:一个数组,可以使用它的名称直接来表示它的起始地址。数组名称实际上就是一个不能被赋值的指针,即指针常量。 关于指针的类型,还应该注意一下几点: 1)可以声明指向常量的指针,此时不能通过指针来改变所指向对象的值,但指针本身可以改变,可以只想另外的对象; 2)可以声明指针类型的常量,这时指针本身的值不能被改变; 3)一般情况下,可以存储任何类型的对西安该地址,就是任何类型的指针都可以赋值给void类型的指针变量。
四、指针运算
指针可以和整数进行加减运算,但是运算规则是比较特殊的。变量时必须指出它所指的对象是什么类型。这里将看到指针进行加减运算的结果与指针的类型密切相关。比如有指针p1和整数n1,p1+n1表示指针p1当前所指位置后方第 n1个数的地址,p1-n1表示指针p1当前所指位置前方第 n1个数的地址。“指针++”或“指针–”表示指针当前所指位置下一个或前一个数据的地址。
五、指针数组
如果一个数组的每个元素都是指针变量,这个数组就是指针数组。指针数组的每个元素都必须是同一类型的指针。声明如下: 数据类型 *数组名[下标表达式]; 由于指针数组的每个元素都是一个指针,必须先赋值后引用,因此,声明数组之后,对指针元素赋初值是必不可少的。
六、用指针作为函数参数
当需要在不同的函数之间传送大量数据时,程序执行时调用函数的开销就会比较大。这是如果需要传递的数据时存放在一个连续的内存区域中,就可以值传递数据的起始地址,而不必传递数据的值,以减少开销,提高效率。以指针作为函数的形参有三个作用: 1)使实参与形参指针指向共同的内存空间,以达到参数双向传递的目的,即通过在被调函数中直接处理主调函数中的数据而将函数的处理结果返回其调用者; 2)减少函数调用时数据传递的开销; 3)通过指向函数的指针传递函数代码的首地址。
七、指向函数的指针
每一个函数都有函数名,实际上这个函数名就表示函数的代码在内存中的起始地址。调用函数的通常是行“函数名(参数表)”的实质就是“函数代码首地址(参数表)”。 函数指针就是专门用来存放函数代码首地址的变量。在程序中可以像使用函数名一样使用指向函数的指针来调用函数。也就是说一旦函数指针指向了某个函数,它与函数名便具有了相同的作用。声明一个函数指针时,也需要说明函数的返回值、形式参数列表,其一般语法如下: 数据类型 (* 函数指针名)(形参表) 数据类型说明函数指针所指函数的返回值类型;第一个圆括号中的内容知名一个函数指针的名称;形参表则列出来该指针所指函数的形参类型和个数。 函数指针在使用之前也要进行赋值,使指针指向一个已经存在的函数代码的起始地址。一般语法为: 函数指针名=函数名; 举例如下:
#include <iostream>
using namespace std;
const float PI = 3.1415926;
void fun1() {
cout<<"fun1" << endl;
}
void fun2(float data) {
cout << "fun2:" << data << endl;
}
int main(){
void (*fun)();
fun1();
fun = fun1;
fun();
void (*pointer)(float);
pointer = fun2;
pointer(PI);
return 0;
}
输出如下:
fun1
fun1
fun2:3.14159
八、对象指针
8.1对象指针的一般概念
对象指针就是用于存放对象地址的变量。对象指针遵循一般变量指针的各种规则,声明对象指针的一般语法形式为: 类名 * 对象指针名; 例子如下:
#include <iostream>
using namespace std;
class Point {
public:
Point(int x = 0, int y = 0): x(x), y(y) {}
int getX() {
return x;
}
int getY() {
return y;
}
private:
int x;
int y;
};
int main(){
Point p(3, 4);
Point* p1 = &p;
cout << p1->getX() << endl;
cout << p1->getY() << endl;
return 0;
}
8.2 this指针
this指针是一个隐含于每一个类的非静态成员函数中的特殊指针(包括构造函数和析构函数),它用于指向正在被成员函数擦欧总的对象。 如8.1节所示,执行getX函数获取横坐标,所使用的语句为:
return x;
系统需要区分每次执行这条语句时被复制的数据成员到底时属于哪一个对象,使用的就是这个this指针,对于系统来讲,每次调用都相当于执行的是:
return this->x;
注:当局部作用域中声明了与类成员同名的标识符时,对该标识符的直接引用代表的是局部作用中所声明的标识符,这是为了访问该类成员,可以通过this指针。
8.3 指向类的非静态成员的指针
指向对象成员的指针使用前也要先声明,再赋值,然后引用。因此首先要声明指向该对象所在类成员的指针。声明指针语句的一般形式为: 类型说明符 类名::*指针名;//声明指向数据成员的指针 类型说明符 (类名::*指针名)(参数表);//声明指向函数成员的指针 声明了指向成员的指针之后,需要对其进行赋值,也就是要确定指向类的哪一个成员。随数据成员指针赋值的一般语法形式为: 指针名=&类名::数据成员名; 访问数据成员时,可通过以下两种语法形式实现: 对象名.
?
*
?类成员指针名 或 对象指针名->
?
*
?类成员指针名
|