C++——指针(一)
指针(pointer)
指针变量也称为指针,它保存着一个内存地址,或者说它的值是内存地址。
我们都知道程序运行的时候要放到内存,而程序中的每个符号都要对应一个内存地址。你可以把一个变量看成一个二元组。第一个元素是内存地址(adress),第二个元素是变量的值(value)。指针就保存着这个变量的地址。
指针利用解引用运算符(*)来访问指针指向的地址中的数据,也就是该变量的值。
可以说指针是C++的核心和灵魂。为什么说C语言和C++相比其他语言如Java和Python更接近底层?就是因为指针的存在。指针可以直接操作内存中的地址,这是其他很多语言无法做到的。但是这也是说C++难的一个重要原因。C++程序员需要手动的申请和释放内存,否则可能导致严重的后果,如内存泄漏。
声明指针
dateType* pointerName;
dateType*声明一个某种数据类型的指针变量,如int*,double*。("*"可以放在任何位置,不一定紧挨着dateType,也可以空一格或者挨着pointerName写,但是更推荐挨着dataType写)。
比如我们声明下面的指针:
//int类型的指针 int* pCount; //char类型的指针 char* pLetter; //string类型的指针 string* pString;
指针赋值
由于指针保存的是地址,所以我们就要先获取到一个变量的地址。这时候就要用到地址运算符(&)。它是一个一元运算符,放在变量的前面,表示该变量的地址。
#include <iostream> using namespace std; int main() { int count = 0; char letter = ‘z‘; string str = "ABC"; int* pCount; char* pLetter; string* pString; pCount = &count; pLetter = &letter; pString = &str; cout << "int类型变量count的值为" << *pCount << ",内存地址为" << pCount << endl; cout << "char类型变量letter的值为" << *pLetter << ",内存地址为" << pLetter << endl; cout << "string类型变量str的值为" << *pString << ",内存地址为" << pString << endl; return 0; }
运行结果:
通过一个指针变量引用变量的方式被称为间接引用,语法如下:
*point
如想让count++可以写为:
//使用指针进行++操作 (*pCount)++; //相当于count++;
细心的同学应该注意到了。上面的字符指针输出地址时,输出的并非地址而是字符的值。
那么为什么int和string类型的指针可以正常输出16进制的内存地址,而char指针输出了值?可以参考下面博客:
常量指针
由于指针直接操作内存,所以为了避免对内存的随意修改,可以将不需要改变的指针声明为常量指针。如:
double radius = 5; //声明指针常量 double* const raduis = &radius;
这样一来就可以防止指针随意被修改而增加安全性。
typedef
C++允许使用typedef关键字来定义同义类型。相当于给原有的数据类型起了一个别名。语法如下:
typedef existingType newType;
如把int定义为integer
//int 与integer同义 typedef int integer; //下一行代码与int number = 10;表达的意思完全一样 integer number = 10;
那么你可能会问,这么做有什么好处呢?我直接写int它不香嘛?
既然有这个关键字就自然有他的道理。之前的博客里说过,一个好的程序不仅仅是执行效率高,而且非常重要的一点是易读性。我们把int同义定义为integer,对于一个不懂C++的人来说(懂英文),他就可以看懂:噢!一个叫number的整数的值是10。
再比如我们刚学的指针,我们为一个int类型指针定义一个同类型的别名:
typedef int* intPointer; int number = 10; intPointer = &number;
把int*同义定义为intPointer,好处有两点。
第一仍然是使程序变得更加易读。
第二是防止在声明指针的时候,防止漏写*
typedef在使用结构体或者联合体的时候,好处更加明显,但这里就不多赘述了。