0
点赞
收藏
分享

微信扫一扫

C++入门学习(4)引用 (讲解拿指针比较)

柠檬的那个酸_2333 2023-11-11 阅读 15

上期回顾

一、引用的诞生

二、引用的概念

我们了解了概念之后,那引用是如何使用的呢?

三、引用的使用

#include <iostream>
using namespace std;
int main()
{
    int a = 3;
    int&a1 = a;
   
    cout << "a = "<< a << endl << "a1 = "<< a1 << endl;
    return 0;
}

四、引用的特性

4.1 引用必须初始化

#include <iostream>
using namespace std;
int main()
{
    int a = 3;
    int&a1;

    return 0;
}

4.2 引用的改变 会 改变引用实体

#include <iostream>
using namespace std;
int main()
{
    int a = 3;
    int&a1 = a;
    
    a1++;
    cout << "a = "<< a << endl << "a1 = "<< a1 << endl;
    return 0;
}

4.3 引用不改变指向,也不可以同时引用多个实体

#include <iostream>
using namespace std;
int main()
{
    int a = 3;
    int&a1 = a;

    int b = 5;
    a1 = b;
    
    cout << "a = "<< a << endl << "a1 = "<< a1 << endl;
    cout << "a的地址为:"<< &a << endl;
    cout << "a1的地址为:"<< &a1 << endl;
    cout << "b的地址为:"<< &b << endl;
    return 0;
}

4.4 一个实体可以有多个引用

#include <iostream>
using namespace std;
int main()
{
    int a = 3;
    int& a1 = a;
    int& a2 = a;
    int& a3 = a;

    cout << "a = "<< a << endl;
    cout << "a1 = "<< a1 << endl;
    cout << "a2 = "<< a2 << endl;
    cout << "a3 = "<< a3 << endl;
    return 0;
}

        我们可以发现,目前的引用都是在引用变量,那是否可以引用常量或者是常变量呢?接下来是我们要讲的重点之一:

五、常引用

在学习之前,我们要先知道这个概念

那什么是常引用呢?就是对常量和常变量的引用,但是一定要记住权限,来看下面的代码:

#include <iostream>
using namespace std;
int main()
{
    const int a = 3;
    int& a1 = a;
    
    return 0;
}

那怎么弄才是对的呢?还是得看权限只能平移和缩小,所以我们更改了代码:

#include <iostream>
using namespace std;
int main()
{
    const int a = 3;
    const int& a1 = a;
    
    return 0;
}

那有没有权限缩小的呢?当然有,来看下面代码:

#include <iostream>
using namespace std;
int main()
{
    int a = 3;
    const int& a1 = a;
    
    return 0;
}

以上都是对常变量的引用,那如何来引用常量呢?

#include <iostream>
using namespace std;
int main() 
{
    const int &a1 = 3;

    return 0;
}

六、引用和引用实体的数据类型不同

我们要了解一个概念,当类型不同的时候,一定会发生类型转换,比如下面的代码:

#include <stdio.h>
int main()
{
    int a = 3;
    double b = a;
    printf("a = %d\nb = %lf",a,b);
    return 0;
}

我们先定义了一个整形变量a,再将a变量赋值给double类型的b,两个类型不同,会发生隐式类型转换,就是把a转换成double类型,再赋值给b,那我们的a的数据类型是什么呢?

从上面可以看出a还是整型,但是不是把a转换成double之后,再赋值给b的吗?怎么a还是int类型?我们带着这样的疑问,去学习一个新的知识: 

凡是涉及到类型的转换,都会产生一个临时变量,存放转换的值。这个临时变量具有常属性

这也就解释了为什么a还是int类型。

我们用图解的方法来看一下:

我们在了解上面的概念之后,看下面的代码:

#include <iostream>
using namespace std;
int main()
{
    int a = 3;
    const double& b = a;
    
    return 0;
}

七、引用的使用场景

其实在上面我们仅仅是在介绍引用该怎么使用,没有介绍引用都用在哪里,所以接下来我们来学习引用使用场景。

7.1 做函数参数

void Swap(int* x,int* y)
{
    int tmp = *x;
    *x = *y;
    *y = tmp;
}

而在C++中,我们可以用引用来解决这个问题:

void Swap(int& x,int& y)
{
    int tmp = x;
    x = y;
    y = tmp;
}

7.2 做返回值

下面的例子主要是讲解,我们用引用做返回值的时候,返回值不可以被销毁。

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

int& Count()
{
    int n = 0;
    n++;
    // ...
    return n;
}
using namespace std;
int main()
{
    int& ret = Count();
    cout << ret << endl;
    return 0;
}

如果我们是下面的代码呢?打印出来的结果又是什么呢?

int& Add(int x,int y)
{
    int z = x + y;
    return z;
}
using namespace std;
int main()
{
    int& ret = Add(1,2);
    cout << ret << endl;
    Add(3,7);
    cout << ret << endl;
    return 0;
}

但是有没有什么办法来解决这样的问题呢?也就是保证返回值不被销毁。

int& Add(int x,int y)
{
    static int z = x + y;
    return z;
}
using namespace std;
int main()
{
    int& ret = Add(1,2);
    cout << ret << endl;
    return 0;
}

所以我们的我们函数返回值要是引用的话,返回值不呢被销毁

八、传值和传引用的效率比较

8.1 函数参数  用  引用和值  的效率比较

#include <time.h>
#include <iostream>
using namespace std;
struct A
{
    int a[10000];
};
void TestFunc1(A a)
{

}
void TestFunc2(A& a)
{

}
void TestRefAndValue()
{
    A a;

    // 以值作为函数参数

    size_t begin1 = clock();
    for (size_t i = 0; i < 10000; ++i)
        TestFunc1(a);
    size_t end1 = clock();

    // 以引用作为函数参数

    size_t begin2 = clock();
    for (size_t i = 0; i < 10000; ++i)
        TestFunc2(a);
    size_t end2 = clock();

// 分别计算两个函数运行结束后的时间

    cout << "TestFunc1(A)-time:" << end1 - begin1 << endl;
    cout << "TestFunc2(A&)-time:" << end2 - begin2 << endl;
}
int main()
{
    TestRefAndValue();
    return 0;
}

8.1 函数返回值用引用和值的效率比较

#include <iostream>
#include <time.h>
using namespace std;
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 < 100000; ++i)
        TestFunc1();
    size_t end1 = clock();

    // 以引用作为函数的返回值类型
    size_t begin2 = clock();
    for (size_t i = 0; i < 100000; ++i)
        TestFunc2();
    size_t end2 = clock();

    // 计算两个函数运算完成之后的时间
    cout << "TestFunc1 time:" << end1 - begin1 << endl;
    cout << "TestFunc2 time:" << end2 - begin2 << endl;
}
int main()
{
    TestReturnByRefOrValue();
    return 0;
}

通过上述代码的比较,发现传值和指针在作为传参以及返回值类型上效率相差很大。这就是引用的优势,不需要开辟临时空间。

九、引用和指针的区别

举报

相关推荐

0 条评论