知识点小结
C++的指针和引用因为涉及到地址和地址当中的存储内容,所以比较容易混淆。首先需要注意的是,
指针和引用存放的都是被引用对象的地址!地址!地址!
比如对于指针,当我们定义一个指针p,比如说int* p = &a时,
指针p必须指向一个地址(即等号右边必须是一个地址)。而*p则表示该地址中包含的内容(即a)。
&这里是取地址符号,不是引用,但作用也是和地址相关,及取出变量的地址。
好,现在我们接触到了第一个地址,就是
变量的地址
,这个地址中存放了变量的内容,在下面的例子中可以认为这个地址中存放着5这个数字。但是需要注意,还有一个地址不能被混淆,就是指向变量的
指针自己的地址
,因为指针也是需要存储空间的。这里指针变成了这个存储空间的内容,其地址和指针指向的地址无关,可以用取地址符号取出验证。
下面来看一下简单的例子。
#include <iostream>
using namespace std;
int main()
{
int a = 5;
//指针p必须指向一个地址,不能用int*p = a
//因为a只是一个变量,不能表示内存地址
int* p = &a;
cout << "a = " << a << endl;
//*p表示指针指向的地址中的内容
cout << "*p = " << *p << endl;
cout << "&a = " << &a << endl;
//p表示指针指向内容的地址
cout << "p = " << p << endl;
//这里&p是取指针的地址,和a及其地址没有任何关系
cout << "&p = " << &p << endl;
return 0;
}
运行的结果如下,即*p == a, p == &a, 而&p是指针p自己的存放地址,与a无关。
以上是最基本的指针操作,但是除了基本的数据类型,指针还可以指向其他的复杂数据类型。以数组为例,数组的特殊之处在于,数组名即可以表示数组的名称,和之前的a一样,可以表示该数组的首地址和之前的&a一样,那么,int*p = a;这样的语句就可以成立。
int b[] = {1, 2, 3};
int* q = b;
cout << "&b = " << &b << endl;
cout << "b = " << b << endl;
//这里可以发现,&b == b
//这里q和b的功能上就完全一致了
cout <<"q = " << q << endl;
cout << "b[1] = " << b[1] << endl;
cout << "q[1] = " << q[1] << endl;
//同样的,q自己的地址和b没有任何关系
cout <<"&q = " << &q <<endl;
对于其他的复杂的或者自己定义的数据类型,在使用指针指向该类型的数据时,需要注意该类型的名称是否可以表示其首地址。还是最一开始的那句话,指针一定要指向地址,不能直接指向变量,除非该变量可以同时表示某个地址。
比如自定义的结构体,结构体名称就不能表示该结构体的地址,所以使用方法要参考一般数据类型的,而不是数组的。
另外,当指针指向结构体时,访问其内容的变量时不能用”.”而要使用”->”, 或者使用”*”号配合”.”一起使用。
struct student
{
string name;
int score;
};
int main()
{
student st1;
student st2;
st1.name = "xiaoli";
st1.score = 70;
// 这里涉及到结构体指针,同样等号右边需要是一个地址
// 这里注意的是,结构体名称不像数组名称一样可以表示地址
student* m = &st1;
cout << "st1.name = " << st1.name <<endl;
cout << "m->name = " << m->name << endl;
cout << "(*m).name = " << (*m).name << endl;
return 0;
}