【C++】引用与指针

这篇具有很好参考价值的文章主要介绍了【C++】引用与指针。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

专栏放在【C++知识总结】,会持续更新,期待支持🌹

c++中引用和指针的代码,C++知识总结,c++,算法,开发语言,Powered by 金山文档

引用

引用的概念

在C++中,引用的本质其实就是给一个已经存在的变量”起别名“。也就是说,引用与它所引用的对象共用一块空间。(同一块空间的多个名字

就比如说,李逵又叫黑旋风,而黑旋风就是指李逵本人,只是名字换了而已。

c++中引用和指针的代码,C++知识总结,c++,算法,开发语言,Powered by 金山文档

引用的特性

1. 引用在定义时必须初始化

2. 一个变量可以有多个引用,但一个引用只能有一个实体对象

#include<iostream>
using namespace std;
int main()
{
    int a = 0;
    //一个变量可以有多个引用,但一个引用只能有一个实体
    int& b = a;//不可以写成int& b;  引用必须在定义时初始化
    int& c = b;
    int& d = c;

    cout << &a << endl;//012FFBD0
    cout << &b << endl;//012FFBD0
    cout << &c << endl;//012FFBD0
    cout << &d << endl;//012FFBD0
    //地址相同,abcd共用同一块空间
    // 另外,引用类型与引用实体的类型必须一致,这里不能写为char & d = a(error)
    return 0;
}

扩展(函数栈帧的创建与销毁)

这里我们进行复习一下关于函数栈帧的一些知识。我们知道,在调用一个函数时, 首先会在内存占用一块空间,用来创建该函数的函数栈帧,当调用结束后,该函数栈帧会被销毁,这里需要注意的是,当 栈帧被销毁后,这里的空间实际上在内存中还是存在的,只不过空间的使用权不再归我们使用并且函数栈帧的销毁,可能会对原有空间进行清理。
c++中引用和指针的代码,C++知识总结,c++,算法,开发语言,Powered by 金山文档
这里可以举个例子来理解一下,就好比说我们在酒店开了一个房间,并且在退房时把我们的电脑放在了房间里,在这里,酒店就相当于内存的存在,而我们退房的那一刻,就好比 函数栈帧销毁的那一刻,但是虽然我们退房了,该房间还是实际存在的,并没有说随着我们的退房而消失,只不过不再归我们使用。并且房间里的东西也 可能会被清理(也可能依然还在),加入此时我们再进行使用该房间,用是可以用,只不过肯定是不合法的,这种行为就好比 空间的非法访问。

引用的使用场景

做参数进行引用(输出型参数)

所谓输出型参数,实际上就是可以影响实参的参数,就比如我们经常写的交换两个变量的值,在以前我们会使用指针来完成传址调用,从而实现形参的改变影响实参,但现在我们可以用引用来实现,如下:
//做参数来使用,由于共用同一块空间,所以这里的c实际上就是a,d实际就是b
void Swap(int& c, int& d)
{
    int tmp = c;
    c = d;
    d = tmp;
}
int main()
{
    int a = 1, b = 2;
    Swap(a, b);
    cout << a << " " << b << endl;//2 1
    return 0;
}

可以做返回值使用

我们先来看这样一段代码:

c++中引用和指针的代码,C++知识总结,c++,算法,开发语言,Powered by 金山文档

这里注意的是:这里的a是局部变量,生命周期会随着栈区的销毁而结束,所以这里返回的实际上并不是a,我们通过查看反汇编发现实际上是借助了一个临时变量来实现的。

那么不禁会有个疑问,假如这里的a不随着栈帧的结束而销毁,那么会不会直接返回a呢?可以试验一下:

c++中引用和指针的代码,C++知识总结,c++,算法,开发语言,Powered by 金山文档

对于这种现象,我们可以把引用作为返回值来使用,从而实现优化,写成如下格式:

//返回值
int& Test()
{
    static int a = 10;
    a++;
    return a;//也会产生临时变量,但是临时变量的类型是int& 也就是a的别名,即临时变量就是返回的a,减少了拷贝操作
}
int main()
{
    int ret = Test();
    return 0;
}

这就是引用返回,即在返回类型前面加上&,虽然也需要借助临时变量的存在,但是由于临时变量的类型为int& ,即临时变量就是a,所以就减少了临时变量的拷贝工作,会使效率得到提升。我们可以来验证一下:

传值返回 vs 传引用返回效率对比

#include <time.h>
struct A { int a[10000]; };
A a;
// 值返回
A TestFunc1() { return a; }
// 引用返回
A& TestFunc2() { return a; }
void TestReturnByRefOrValue()
{
    // 以值作为函数的返回值类型
    size_t begin1 = clock();
    for (size_t i = 0; i < 1000000; ++i)
        TestFunc1();
    size_t end1 = clock();
    // 以引用作为函数的返回值类型
    size_t begin2 = clock();
    for (size_t i = 0; i < 1000000; ++i)
        TestFunc2();
    size_t end2 = clock();
    // 计算两个函数运算完成之后的时间
    cout << "TestFunc1 time:" << end1 - begin1 << endl;
    cout << "TestFunc2 time:" << end2 - begin2 << endl;
}

int main()
{
    TestReturnByRefOrValue();
}

运行结果如下:

c++中引用和指针的代码,C++知识总结,c++,算法,开发语言,Powered by 金山文档

我们发现传引用返回对比传值返回,效率会有显著提高(作为参数使用时,传引用参数的效率也会高于传值作为参数的效率)

当然,传引用作为返回值的使用是有一定的限制的,我们发现上面的代码能使用传引用返回的原因在于,返回的变量不会随着作用域的销毁而销毁假如说返回的对象出了作用域后已经销毁,则必须使用传值返回,否则返回的结果是不确定的!

c++中引用和指针的代码,C++知识总结,c++,算法,开发语言,Powered by 金山文档

并且引用用作返回时,还可以修改返回对象(后面的学习会用到很多,这里简单介绍)

如下:

#define N 10
typedef struct ARR
{
    int arr[N];
}ARR;

int& PosARR(ARR& arr,int i)
{
    return arr.arr[i];//这里的arr就是main函数里的arr,不会随着PosARR函数的结束而销毁,所以可以用引用返回
}
int main()
{
    ARR arr;
    for (int i = 0; i < N; i++)
    {
        PosARR(arr, i) = i * 10;//引用返回可以修改返回对象,这里的返回对象为arr.arr[i],对此进行修改
    }
    for (int i = 0; i < N; i++)
    {
        cout << arr.arr[i] << " ";//0 10 20 30 40 50 60 70 80 90
    }
    return 0;
}

总结

引用可以用作参数来使用(输出型参数),也可以用作返回使用,用作返回使用时返回的对象必须是出了所在函数作用域后不会销毁的(比如static修饰的变量,全局变量,malloc......),并且引用返回时,返回的对象可以被修改。同时还可以减少拷贝提高效率。

常引用

我们要记住这样一句话:指针和引用在赋值或者初始化时,权限可以被缩小或者保持,但不可进行修改。

这是什么意思呢?通过以下代码进行了解:

    // 权限放大(error)
    //const int c = 2;//const 修饰的常量不可以进行修改,可以理解只具有读的属性,不具有写的属性,而d可以修改,所以权限被放大
    //int& d = c;//这里正确写法应为const int& d=c;

    //const int* p1 = NULL;
    //int* p2 = p1;//同上,前面加个const即可,const int* p2=p1; (√)

    // 权限保持
    const int c = 2;
    const int& d = c;

    const int* p1 =NULL;
    const int* p2 = p1;

    // 权限缩小
    int x = 1;//x可以进行修改,可以理解为具有读和写的属性,而x是const修饰的,只具有读的属性,权限缩小了
    const int& y = x;

    int* p3 = NULL;
    const int* p4 = p3;//同上

不仅如此,由于所谓临时变量具有常性(即不可被修改)的原因,也会出现以下的情况:

    int i = 0;
    //double& p = i;//error
    //由于int到double类型发生类型转换,而类型转换会产生临时变量,临时变量又具有常性(只可读)
    //因此在前面加上const即可
    const double& p=i;//(√)

这也就解释了上文说到的引用类型与引用实体的类型必须一致,同样,在函数中也一样适用:

int add(int x, int y)
{
    int c = x + y;
    return c;//实际上是借助临时变量,将c拷贝给临时变量,再将临时变量拷贝给p
}
int main()
{
    int a = 1, b = 2;
    //int& p = add(a, b);//由于临时变量具有常性的特点,所以不可以这样写
    //前面加上const 即可
    const int& p = add(a, b);

    return 0;
}

引用与指针

&是一个很熟悉的符号,与指针有关,用在变量前面就是取地址符号,用在类型后面则为引用符号,那么指针与引用之间是否有着什么关系呢?

int a=0;
int* p=&a;//&:取地址符
int& b=a;//&:引用

指针与引用的相同点

实际上,引用与指针,两者之间在底层实现上其实是一样的,我们可以来进行验证

c++中引用和指针的代码,C++知识总结,c++,算法,开发语言,Powered by 金山文档

当然,两者之间也存在着很大的区别。

指针与引用的不同点

首先就是在语法概念上的区别, 引用只是同一个实体的不同名称, 不会单独开辟空间,但是指针会在内存开辟一块4/8byte大小的空间。
引用在定义时 必须初始化,指针没有要求
引用在初始化时引用一个实体后,就 不能再引用其他实体,而指针可以在任何时候指向任何一个同类型实体(这一点也就意味着 引用并不能实现完全替代指针,就比如在链表这里,用来指向下一个节点的变量类型,只能是指针)
有多级指针,但是没有多级引用
引用自加即引用的实体增加1,指针自加即指针向后偏移一个类型的大小
引用比指针使用起来相对更安全(野指针)

...

看法:

因此对于指针与引用,我们只能是说引用相较于指针来说,更加容易理解使用,并且也不会存在空引用的问题,但是在一些场景下,引用自身的特点(不能改变指向)也存在着使用限制,此时就得用指针来实现

end

生活原本沉闷,但跑起来就会有风!🌹文章来源地址https://www.toymoban.com/news/detail-784427.html

到了这里,关于【C++】引用与指针的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • C++的指针和引用

    C++中内存单元内容和地址 内存由很多的内存单元组成,这些内存单元用于存放各种类型数据; 计算机对内存的每个内存单元都进行了编号,这个编号就称为内存地址,地址决定了内存单元在内存中的位置; 记住这些内存单元地址不方便,因此C++语言的编译器让我们通过名字

    2024年02月06日
    浏览(35)
  • 【C++】引用与指针

    专栏放在【 C++知识总结 】,会持续更新,期待支持 🌹 引用的概念 在C++中,引用的本质其实就是给一个已经存在的变量 ”起别名“ 。也就是说, 引用与它所引用的对象共用一块空间 。( 同一块空间的多个名字 ) 就比如说,李逵又叫黑旋风,而黑旋风就是指李逵本人,只

    2024年02月02日
    浏览(33)
  • c++的引用和指针

    我们要清楚的知道,使用指针和引用都可以的传入函数的main函数的变量在局部函数改变值时,main函数里面相应的变量也会改变值。但他俩的方式不同。 我们先来说指针,指针传入局部参数时,他会在创建个局部指针变量,然后把传入的地址赋值给局部的指针变量,然后修改

    2024年02月09日
    浏览(38)
  • 【C++那些事儿】函数重载与C++中的“指针“——引用

    君兮_的个人主页 即使走的再远,也勿忘启程时的初心 C/C++ 游戏开发 Hello,米娜桑们,这里是君兮_,我之前看过一套书叫做《明朝那些事儿》,把本来枯燥的历史讲的生动有趣。而C++作为一门接近底层的语言,无疑是抽象且难度颇深的。我希望能努力把抽象繁多的知识讲的生

    2024年02月08日
    浏览(37)
  • C++[第五章]--指针和引用

    引用就是别名,引用定义时必须初始化: int a; int b=a; //b即为a的别名 如果不是形参,必须初始化,引用某一变量 指针和c一样; this指针 在类的成员函数中使用,表示当前对象; C++11 新增了一种引用 类型 引用名 = 右值表达式; 引入右值引用如: 编译器允许我们为 num 左值建立

    2024年02月15日
    浏览(31)
  • C++拾遗(四)引用与指针

    引用和指针是两种不同的概念,尽管它们在某些方面有一些相似之处,但它们在功能和用途上是有所区别 引用:引用是别名,是对已存在变量的另一个称呼,一旦一个变量被引用,就不能再被引用其他变 量。 int a = 10; int ref = a;   这里, ref  是  a  的引用,它们引用的是同

    2024年01月25日
    浏览(44)
  • C++中的引用及指针变量

    目录 1.1 C++中的引用 1.2 C++中的指针变量(pointer) 1.1 C++中的引用 C++中的引用(reference)是一种特殊的变量,它是某个已存在变量的另一个名字。引用变量与指针变量类似,但引用变量必须在声明时进行初始化,并且一旦引用变量与某个变量关联起来,就无法再与其他变量关

    2024年01月20日
    浏览(32)
  • C++中const,指针和引用

    在线C/C++编译器,可以试着运行代码。 在C语言中,const修饰的量称为 常变量 (在编译过程中,const就是当成变量的编译生成指令的),不可以直接修改它的值,但是可以 通过地址进行修改其对应的值 。并且const修饰的变量可以不进行初始化,编译器最后默认赋值为0。 然而在

    2024年02月13日
    浏览(30)
  • 【C++初阶(三)】引用详解(对比指针)

    💓博主CSDN主页:杭电码农-NEO💓   ⏩专栏分类:C++初阶之路⏪   🚚代码仓库:NEO的学习日记🚚   🌹关注我🫵带你学习排序知识   🔝🔝 C语言中有一利器: 指针 而C++中增加了另一利器: 引用 这两个板块的存在 极大了提升了C/C++的可用性! 本篇文章将给大家详细讲解引用 并

    2024年02月12日
    浏览(37)
  • C++智能指针学习——小谈引用计数

    目录 前言 控制块简介 共享控制块 引用计数与弱引用计数创建过程 __shared_ptr __shared_count _Sp_counted_base 弱引用计数增加过程 再谈共享控制块 __weak_count 引用计数增加过程 弱引用计数的减少过程 弱引用计数减为0 引用计数的减少过程 引用计数减为0 参考文章 本文结合源码讨论

    2024年04月08日
    浏览(38)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包