指针
每一个变量都有一个内存位置,每一个内存位置都定义了可使用连字号(&)运算符访问的地址,它表示了在内存中的一个地址。
请看下面的实例:
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指向的数组
动态内存分配在许多情况下非常有用,例如当程序依赖于输入时。例如,当你的程序需要读取一个图像文件时,它不会事先知道图像文件的大小和存储图像所需的内存。
文章评论