前言:
文章中举了大量的例子,希望读者可以耐住性子好好读一下,相信会对指针和引用有底层的了解。
1. 指针
1. 概念:指针就是地址, 指针变量是用来存放指针(地址)的变量。
2. * 作用:1.声明指针变量;2.表示指向(取出对应的普通型变量的值)。
3. 举例:
实例一:
代码:
#include<iostream>
using namespace std;
int main(){
int number = 1234; //定义普通变量
int *point; //定义指针型变量
point = &number; //将number的地址赋值给point
int *point2 = point; //将point中存放的number的地址赋值给point2
//此时point和point2中都存放了number的地址。
cout << "number变量的地址:" << &number << endl;
cout << "指针变量point的值:" << point << endl;
cout << "指针变量point2的值:" << point2 << endl;
cout << "number变量的值:" << number << endl;
cout << "指针变量point所指向的普通变量的值:" << *point << endl;
cout << "指针变量point2所指向的普通变量的值:" << *point2 << endl;
//重要地方
cout << "point指针变量的地址:" << &point << endl;
return 0;
}
控制台输出结果:
number变量的地址:0x69fef8
指针变量point的值:0x69fef8
指针变量point2的值:0x69fef8
number变量的值:1234
指针变量point所指向的普通变量的值:1234
指针变量point2所指向的普通变量的值:1234
point指针变量的地址:0x69fef4 //注意:和number变量的内存地址是不同的
解释:可以看出:
1.指针变量point中存放的值是它所指向的普通变量number的内存地址。也就是说,指针变量point的存储空间中存放的值是一个地址。这个地址是它所指向的普通变量的内存地址。
2.普通变量number的值可以通过它对应的指针变量point来获得。
3.但是point的内存地址不是它指向的普通变量的内存地址,这一点容易混淆。
实例二:
代码:
#include<iostream>
using namespace std;
typedef struct node{
int data;
struct node *next;
}Node;
void f(Node *node3){
node3->data = 87654;
}
int main(){
Node node1;
node1.data = 1111;
Node node2;
node2.data = 2222;
Node *head = &node1;
Node *head2 = &node2;
head2->data = 9999;
f(head);
cout<< "node1: " << node1.data << endl;
cout<< "node2: " << node2.data << endl;
cout<< "head: " << head->data << endl;
cout<< "head2: " << head2->data << endl;
return 0;
}
控制台输出结果:
node1: 87654
node2: 9999
head: 87654
head2: 9999
实例三:
代码:
#include<iostream>
using namespace std;
#define MAX 4
int main(){
int i,j;
int A[MAX][MAX];
int * B;
int k = 0;
for(i=1;i<=3;i++){
for(j=1;j<=3;j++){
A[i][j] = ++k;
//cin>>A[i][j];
}
}
B = A[3]; //把数组第四行的首地址赋值给指针变量B。
for(i=1;i<=3;i++){
cout<<B[i]<<" ";
}
return 0;
}
控制台输出:
7 8 9
解释:对于一个二位数组A[MAX][MAX],A[i]表示的就是第i+1行的首地址。B = A[i]就是把数组第i+1行的首地址赋值给B,B就相当于变成了数组,它的值就是数组第i+1行的值。这样的好处在于用不同的变量操纵同一片内存空间,对于数组重复使用较为方便。
2. 引用
1. 概念: 引用变量是变量的别名,普通变量和对应的引用变量使用相同的地址空间。
2. &作用:1.取出变量对应的地址;2.声明引用型变量。
3. 举例:
代码:
#include<iostream>
using namespace std;
int main(){
int number = 4321;
int &refer = number; //必须要初始化
int &refer2 = refer;
cout << "变量number的地址:" << &number << endl;
cout << "引用变量refer的地址:" << &refer << endl;
cout << "引用变量refer2地址:" << &refer2 << endl;
cout << "number变量的值(变量):" << number << endl;
cout << "引用变量refer的值:" << refer << endl;
cout << "引用变量refer2的值:" << refer2 << endl;
refer = 5678; //对refer重新赋值。
cout << "number变量的值(变量):" << number << endl;
cout << "引用变量refer的值:" << refer << endl;
cout << "引用变量refer2的值:" << refer2 << endl;
return 0;
}
控制台输出结果:
变量number的地址:0x69fef4
引用变量refer的地址:0x69fef4
引用变量refer2地址:0x69fef4
number变量的值(变量):4321
引用变量refer的值:4321
引用变量refer2的值:4321
number变量的值(变量):5678
引用变量refer的值:5678
引用变量refer2的值:5678
解释:可以看出
1.普通变量和它对应的引用变量共用同一块内存空间。可以把引用变量refer视作是普通变量number的别名,名称不同,但是内存地址相同。refer和number的值是相同的。
2.refer值的改变会引起number值的改变。
3. 指针和引用的区别
1. 引用在定义的时候必须要初始化。指针可以先声明再初始化。
2. 引用的值不可修改。指针的值可以修改。
3. 引用不可为空,必须连接一个内存地址。指针可以为空(NULL)。
错误示例:
int number = 4321;
int &refer;
refer = number;
错误信息:error: 'refer' declared as reference but not initialized (这个引用没有被初始化)。
正确示例:
int number = 4321;
int number2 = 5678;
int &refer = number;
refer = number2; //变量的值之间的赋值
cout << "number变量的地址(取地址符):" << &number << endl;
cout << "number2变量的地址(取地址符):" << &number2 << endl;
cout << "number变量的地址(引用refer):" << &refer << endl;
cout << "number变量的值(引用refer):" << refer << endl;
cout << "number变量的值(number):" << number << endl;
输出信息:
number变量的地址(取地址符):0x69fed8
number2变量的地址(取地址符):0x69fed4
number变量的地址(引用refer):0x69fed8
number变量的值(引用refer):5678
number变量的值(number):5678
解释:可以看出,refer被重新赋值之后,连接的内存地址仍然是number的内存地址,但是值变成了number2的值。说明refer连接的内存地址在定义的时候就会确定并且不再更改。
4.结构体
1. 我们主要讨论几种常见的形式。
typedef struct node{
int data;
struct node *lchild, *rchild;
int ltag,rtag;
}ThreadNode,*ThreadTree;
2. 用以上的结构体声明变量
ThreadNode node1;
node1.data = 9999;
ThreadNode *node2 = (ThreadNode *)malloc(sizeof(ThreadNode));;
node2->data = 8888;
node2 = &node1; //node2暂时性的连接node1的内存地址
node2->data = 7777; //node2的值改变node1的值也改变。
ThreadTree tree1 = (ThreadTree)malloc(sizeof(ThreadTree));
tree1->data = 1111;
ThreadTree &tree2= tree1; //引用类型,tree2永远连接tree1的内存地址
tree2->data = 2222; //tree2改变tree1也改变
cout<< "node1: " <<node1.data <<endl;
cout<< "node2: " <<node2->data <<endl;
cout<< "tree1: " <<tree1->data <<endl;
cout<< "tree2: " <<tree2->data <<endl;
控制台输出结果:
node1: 7777
node2: 7777
tree1: 2222
tree2: 2222