今天我们来学习C++的引用和指针。
一、引用
1. 什么是引用:引用为对象起的另外一个名字,引用即(对象)别名。通俗解释:当定义一个对象时,我们分配存储空间和对应的地址,把对象存储空间理解为房间,把对象名理解为房间名,现在我们给这个房间取了一个新的名字(原来的名字也保留),那么这个新名字即为该房间的别名,使用别名(新名字,即引用)和正名(老名字,变量名)都可以访问这个房间。
2. 引用必须初始化。
3. 定义引用时是把引用与它的初始值绑定而非给引用赋值
4. 允许定义多个引用。
// C++基础:引用
#include<iostream>
int main()
{
int var=10;
//引用必须初始化,且不能用常量初始化
//错误定义1:int &VAR1;
//错误定义2:int &VAR1 = 10;
//这是引用,此时VAR1和var的内存地址是一致的。
int &VAR1 = var;
//这是定义了一个新的变量,此时的VAR2和var的内存地址是不一致的。是两个不同的变量,只是用var的值初始化了VAR2
int VAR2 = var;
std::cout << VAR1 << " " << VAR2 << std::endl;
//输出:10 10
//引用本身不是对象,故不能定义引用的引用
//emmmmmmmmmmm书上是这么说的,但这段代码还是跑出来了。
int &VAR3 = VAR1;
std::cout << VAR3 << std::endl;
//输出:10
//允许定义多个引用。
int &Ref1 = var, &Ref2 = var;
std::cout << Ref1 << " " << Ref2 << std::endl;
//输出:10 10
system("pause");
return 0;
}
5. 对引用的操作就是对其绑定的对象的操作。
//对引用的操作,即是对其绑定的对象的操作
int i = 1;
double d = 0.1;
int &r1 = i;
double &r2 = d;
std::cout << "i,d,r1,r2: " << i << "," << d << "," << r1 << "," << r2 << std::endl;
//输出为:1,0.1,1,0.1
r2 = 3.14159;
std::cout << "i,d,r1,r2: " << i << "," << d << "," << r1 << "," << r2 << std::endl;
//输出为:1,3.14159,1,3.14159
r2 = r1;
std::cout << "i,d,r1,r2: " << i << "," << d << "," << r1 << "," << r2 << std::endl;
//输出为:1,1,1,1
i = r2;
std::cout << "i,d,r1,r2: " << i << "," << d << "," << r1 << "," << r2 << std::endl;
//输出为:1,1,1,1
r1 = d;
std::cout << "i,d,r1,r2: " << i << "," << d << "," << r1 << "," << r2 << std::endl;
//输出为:1,1,1,1
二、指针
(指针算是C系列中最复杂最难的知识点之一,笔记不清楚望多包涵)
1. 指针:指向另外一种类型的复合类型。(或:存放某个对象地址的一种复合类型)
2. 指针与引用的区别: 首先,指针本身就是一个对象(引用本身不是对象),允许对指针赋值和拷贝,一个指针前后可以指向不同的对象。其次,指针无须定义时赋初值。
3. 指针的定义:
int var1 = 10;
double var2 = 2.1;
//定义方法1
int *p1; //定义了一个指针p1
p1 = &var1; //将变量var1的地址赋给了p1
//定义方法2:定义指向变量var2的指针p2
double *p2 = &var2
//注意:指针的类型要与它所指的对象严格匹配
4. 利用指针访问对象:如果指针指向了一个对象,可以通过解引用符对其进行访问(*),此时*号为运算符,功能是计算指针所指对象的值,下例中*p1就是计算p1指针所指向的对象var1的值。区别于声明时的*号为声明符。类似的还有&符号,定义引用时为声明符,表达式中为运算符,计算变量地址。
int var1 = 10;
double var2 = 2.1;
//指针定义
int *p1; //定义语句,*为声明符
p1 = &var1;
double *p2 = &var2;
//利用指针访问对象
std::cout << *p1 << " " << var1 << " " << *p2 << " " << var2 << std::endl;//此处*为运算符
//输出:10 10 2.1 2.1
*p1 = 3; //*p1为变量var1的值,所以这是在通过p1向var1赋值。
*p2 = 1.1;
std::cout << *p1 << " " << var1 << " " << *p2 << " " << var2 << std::endl;
//输出:3 3 1.1 1.1
system("pause");
return 0;
5. 空指针:不指向任何对象的指针即为空指针。定义如下:
int *p1; //定义一个指针
p1 = 0; //p1的的值赋字面常量0
int *p2 = NULL; //定义一个空指针
6. 赋值和指针:观察以下demo,要注意的是操作的是指针的值还是指针所指向的对象的值。
//demo1:交换两指针所指向的对象
int var1 = 10;
int var2 = 20;
int *p1 = &var1, *p2 = &var2;
int *p3 = NULL;
std::cout << *p1 << " " << *p2 << std::endl;
//输出:10 20
p3 = p1; //p1的值赋给p3,所以p1和p3的值相同(指针时保存地址的对象,即保存的地址相同),指向同一个变量,即都指向var1
p1 = p2; //p2的值赋给p1,这时p2和p1指向同一对象,都指向var2,p3没变,指向var1
p2 = p3; //p3的值赋给p2,这是p3和p2指向同一对象,都指向var1,p1没变,指向var2
std::cout << *p1 << " " << *p2 << std::endl;
//输出:20 10
system("pause");
return 0;
//demo2:交换变量值
int var1 = 1, var2 = 2;
int *p1 = &var1, *p2 = &var2;
int temp = 0;
temp = *p1; //将p1所指向对象的值赋给temp
*p1 = *p2; //将p2所指向对象的值赋给p1所指向的对象
*p2 = temp; //将temp赋值给p2所指向对象
std::cout << var1 << " " << var2 << std::endl;
system("pause");
return 0;
7. void *指针:一种特殊类型的指针,可用于存放任意对象的地址。void类型指针不能访问其指向对象。
int var1 = 1;
double var2 = 2.1;
void *p;
p = &var1;
std::cout << *p << std::endl;
//输出报错,不能访问
p = &var2;
std::cout << *p << std::endl;
//输出报错,不能访问
8. 指向指针的指针(套娃?):指针本身是一个对象,像其他对象一样也有地址,也可以有其他的指针指向它。即指向指针的指针。
int var = 10;
int *p = &var; //p指向一个int的数
int **pp = &p; //pp指向一个int型的指针,即指向指针的指针