指针与引用

指针

1. 什么是指针:

        指针即地址,我们在编写程序时,每创建一个变量,计算机就分配一块内存空间来存储这个变量,而指针就是一个标记,能让我们通过指针来访问其指向的空间的内容,并对该空间的内容进行修改

2. 指针变量:

  • 指针变量的类型与大小:我们熟知的数据类型有int, short, float, double, char等,而不同的类型的变量就需要相对应的指针变量来存储。而指针变量的大小只与当前所处的环境有关在X86环境下,任何类型的指针变量大小均为4字节;在X64情况下,大小均为8字节
  • 如何使用指针变量:见示例代码
//示例:
#include<iostream>
using namespace std;
int main() {
    int p = 0;
    int *ptr = &p;//创建一个名为ptr的指针变量,并将其初始化为p的地址(&为取地址符)
    *ptr = 3;//*与指针变量结合就可以访问存在ptr的地址的变量,改变*指针变量的值,
             //就可以改变存在这个指针变量所存储的地址的变量
    cout << p << ' ';
    return 0;
}

3. 野指针与空指针: 

1. 野指针与空指针的定义:

  • 野指针:指针指向的位置是不确定的
  • 空指针:明确被赋值为NULL的指针,表示不指向任何有效的地址

2. 野指针的成因: 

  • 指针未初始化
#include <iostream>
using namespace std;
int main()
{
    int* p;//局部变量未初始化,默认未随机值
    *p = 20;
    return 0;
}
  • 指针越界访问
#include <iostream>
using namespace std;
int main()
{
    int arr[10] = { 0 };//0 0 0 0 0 0 0 0 0 0(10个数)
    int* p = &arr[0];
    int i = 0;
    for (i = 0; i <= 11; i++);//循环了12次
    {
        *p = i;
        p++;
    }
    cout << n << endl;
    return 0;
}
  • 指针指向的空间已被释放
#include <iostream>
using namespace std;
int* test()
{
    int n = 100;//n是局部变量
    return &n;
}
int main()
{
    int* p = test();
    cout << *p << endl;
    return 0;
}
/*
上诉代码中,n是局部变量,所以n的生命周期就是局部范围,当出了范围后,n会被销毁。通过
return &n导致n的地址被返回。p接收了这个地址。在&n返回的时候,n所占的空间就不属于n了。
这时候p在拿着刚才返回的地址去找n,根本找不到。因此,当p得到地址的时候,就已经是野指针了
*/

 3. 如何避免野指针:

  • 使用指针变量时初始化,明确指针指向哪里时直接赋地址;不知道时直接赋为NULL
  • 指针变量被释放时及时置空
  • 注意指针越界问题
  • 指针使用前检查指针变量是否为空指针

 4. 指针作为函数参数传递:

        见文章:C++函数参数的传递方式(值传递、址传递、引用传递、const在传递函数参数时的作用)_c++ 编译器 对函数参数 值传递和const引用传递 优化-优快云博客

5. 指针数组与数组指针: 

  • 指针数组:本质上是数组,数组内元素存的是指针
定义方式: 数据类型 *数组名[指针数组长度];
  • 数组指针:本质上是指针,存放的是数组的地址
定义方式: 数据类型 (* 数组名)[数组指针的长度]

 6. 函数指针:

        C 语言中,函数不能嵌套定义,也不能将函数作为参数传递。但是可以取得函数名为该函数的入口地址。我们可以定义一个指针指向该地址,将指针作为参数传递

        函数指针的定义方式:

数据类型 (*函数指针名)(函数参数);

        注意:函数指针在进行“*”操作时,可以理解为执行该函数。函数指针不同与数据指针,不能进行+整数操作。

        函数指针的使用示例:

#include <iostream>
using namespace std;

// 定义一个普通函数
int add(int a, int b) {
    return a + b;
}

int main() {
    // 定义一个函数指针,该指针指向一个返回int类型,接受两个int类型参数的函数
    int (*funcPtr)(int, int);

    // 将add函数的地址赋值给函数指针
    funcPtr = add;

    // 通过函数指针调用函数
    int result = funcPtr(3, 5);
    cout << "3 + 5 = " << result << endl;

    return 0;
}

引用

1. 引用的定义:

        给已经存在的变量取别名,编译器不会为引用变量开辟内存空间,它和它引用的变量共用同一块内存空间

        引用的定义方式:

数据类型 &引用变量名 = 变量

2. 引用的特性:

  • 引用的指向不能修改(因为引用的底层是指针常量
  • 引用必须在定义时初始化,且不能初始化为空

3. 左值引用、右值引用与万能引用:

  • 左值引用:只能接收左值 
int a = 10;
int& ref_a = a;
  •  右值引用:只能接收右值
int&& rref = 20;
  •  万能引用:万能引用是一种特殊的引用,它既能接收左值又能接收右值
//接收左值
int a = 10;
const int ref_a = a;

//接收右值
const int rref = 20;

         万能引用的优缺点:优点 既能接收左值又能接收右值;缺点 值不能被修改

4. 引用与指针的区别:

  • 引用在定义时必须初始化,但指针没做要求
  • 引用的指向不能修改,指针可以
  • 引用不能为空,指针可以
  • 引用比指针形式上更加简洁,代码的可读性更高
  • 引用比指针更安全(指针有野指针、空指针等)
  • 引用没有多级,指针有多级
  • 访问实体的方式不同,指针需要显示解引用;引用则是编译器自行处理
  • sizeof引用所得到的值是指引用对象所指对象的值,sizeof指针所得的是指针变量本身的值
  • 引用做函数参数传递的是实参本身,指针做函数参数传递的是指针变量的值

END

        本文讲解了引用与指针的定义方式、使用方式、使用的注意事项以及指针与引用的区别。希望可以对你有帮助 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值