指针

正如您所知道的,每一个变量都有一个内存位置,每一个内存位置都定义了可使用连字号(&)运算符访问的地址,它表示了在内存中的一个地址。

请看下面的实例:

int score = 5;
cout << &score << endl;

//输出 "0x29fee8"

这将输出定义的变量地址。
指针是一个变量,其值为另一个变量的地址,即,内存位置的直接地址。

所有指针的值的实际数据类型,不管是整型、浮点型、字符型,还是其他的数据类型,都是一样的,都是一个代表内存地址的长的十六进制数。

提示:不同数据类型的指针之间唯一的不同是,指针所指向的变量或常量的数据类型不同。

指针是一个变量,就像其他变量或常量一样,您必须在使用指针存储其他变量地址之前,对其进行声明。

星号 * 用来声明一个指针,与乘法中使用的星号是相同的。但是,在这个语句中,星号是用来指定一个变量是指针。

以下是有效的指针声明:

int    *ip;    /* 一个整型的指针 */
double *dp;    /* 一个 double 型的指针 */
float  *fp;    /* 一个浮点型的指针 */
char   *ch;    /* 一个字符型的指针 */

就像变量一样,我们给这个指针一个名字并且定义这个指针指向的类型。

提示:星号可以放在数据类型或变量名的旁边,也可以放在中间。

使用指针

在这里,我们将一个变量地址赋值给指针:

int score = 5;
int *scorePtr;
scorePtr = &score;

cout << scorePtr << endl;

//输出 "0x29fee8"

上面的代码声明了一个指向scorePtr的整型的指针,并使用&符号(地址)运算符为其赋值score变量的内存位置。

现在,scorePtr的值是score的内存位置。

指针运算符

在C++ 中,有两个指针运算符:

取地址运算符(&):返回操作数的内存地址。

解引用操作符(*):返回位于操作数所指定地址的变量的值。

下面是一个例子:

int var = 30;
int *p;
p = &var;

cout << var << endl;
// 输出 30 (var的值)

cout << p << endl;
// 输出 0x28ff18 (var的内存位置)

cout <<

p << endl; /

输出 30 (变量的值存储在指针p中) */

提示:星号(*)用于声明一个指针,用于指示它是一个指针(星号是它的类型复合说明符的一部分)的简单目的。请不要将其与用于获取位于指定地址的值的解引用运算符混淆。它们只是用相同的符号表示的两种不同的东西。

解引用运算符

解引用运算符(*)基本上是指针指向的变量的别名。

下面是一个例子:

int x = 3;
int *p = &x;

x = x + 2;
x = *p + 2;
*p = *p + 2;

在代码中,前面的所有三个语句都是相同的,并返回相同的结果。我们可以通过解引用变量的指针来访问变量。

当p指向变量x时,解引用指针(*p)的方式与变量x完全相同。

动态内存

了解动态内存在 C++ 中是如何工作的是成为一名合格的 C++ 程序员必不可少的。

C++ 程序中的内存分为两个部分:

栈:在函数内部声明的所有变量都将占用栈内存。
堆:这是程序中未使用的内存,在程序运行时可用于动态分配内存。
在 C++ 中,您可以使用 new 运算符为给定类型的变量在运行时分配堆内的内存,这会返回所分配的空间地址。

下面是使用 new 运算符来为任意的数据类型动态分配内存的通用语法:

new data-type;

在这里,data-type 可以是包括数组在内的任意内置的数据类型,也可以是包括类或结构在内的用户自定义的任何数据类型。

下面是一个例子:

new int;

这将分配在堆上存储整数所需的内存大小,并返回该地址。

在C++ 中,分配的地址可以存储在一个指针中,然后可以通过解除引用来访问变量。

下面是一个例子:

int *p = new int;
*p = 10;

我们为一个整数动态地分配内存,并为其赋值10。

指针p作为局部变量存储在堆栈中,并将堆的分配地址保存为其值。10的值存储在堆中的那个地址处。
对于堆栈中的局部变量,管理内存是自动执行的。

在任何时候,当您觉得某个已经动态分配内存的变量不再需要使用时,您可以使用 delete 运算符释放它所占用的内存。如下所示:

delete pvalue;        // 释放 pvalue 所指向的内存

下面是一个例子:

int *p = new int; // 为变量请求内存
*p = 10; // 在分配的地址存储值

cout << *p << endl; 

delete p; // 释放内存

提示:忘记释放使用new关键字分配的内存将导致内存泄漏,因为内存将保持分配状态,直到程序关闭。

悬空指针

在 C++ 中,delete 运算符释放为变量分配的内存,但不会删除指针本身,因为指针存储在堆栈中。

指向不存在的内存位置的指针称为悬空指针。

下面是一个例子:

int *p = new int; // 请求内存
*p = 10; // 存储值

delete p; // 释放内存
// 现在p是一个悬空指针

p = new int; // 重新使用一个新的地址

提示:

NULL指针是一个值为零的常量,在几个标准库(包括iostream)中定义。

在声明它时,将NULL指定给一个指针变量是一个好习惯,以防您没有准确的地址分配。分配NULL的指针称为空指针。例如:int * ptr = NULL;

在C++ 中,动态内存也可以分配给数组。

下面是一个例子:

int *p = NULL; // 指针初始化为null
p = new int[30]; // 请求内存
delete [] p; // 删除由p指向的数组

动态内存分配在许多情况下非常有用,例如当程序依赖于输入时。例如,当你的程序需要读取一个图像文件时,它不会事先知道图像文件的大小和存储图像所需的内存。

最后修改:2022 年 12 月 05 日
如果觉得我的文章对你有用,请随意赞赏