C++入门编程 ---- 助你更好理解C++的奥妙(二)

简介: C++入门编程 ---- 助你更好理解C++的奥妙(二)

引用的一般使用场景:

分为:做 性参 和 返回值


做形参:

就好像是我们前面写的 那两个swap函数一样 再来就是:

大家都知道我们的C语言的 scanf("%d", &a ); 那这里的取地址操作就是因为我们的scanf函数回去我们缓冲区里面区提取数据 如果直接给给 a 这样是肯定不行的 这里的 &a 就是scanf函数的参数 我们传 a 的地址进去 在里面对a的地址解引用改变a 这样对a进行的改变才会影响到我们传进去的参数(实参)

那现在有了我们的引用操作还需要这样嘛 


我们利用引用传参 的效率是比 我们直接传值 的效率要高的

       因为 我们以值作为参数或者返回类型的时候,在开始的传参 和 返回期间 函数不会直接传递实参或者直接把返回值直接返回 而是会传递实参的临时拷贝或者是返回变量的临时拷贝 如果这样的话 那我们的效率可想而知是很低下的 并且如果我们参数或者返回值类型很大时 效率会更低 就好比是 结构体类型


做返回值:

大家看这样的结果是什么

int test()
{
    static int n=0;
    n++;
    return n;
}
int main()
{
    cout<<test()<<endl;
    cout<<test()<<endl;
    cout<<test()<<endl;
}


答案: 1  2  3  这里大家要注意一个点就是我们的 static 语句是只执行一次的 之所以提这个我们在了解引用做返回值之前 我们要理清楚值返回的特性

27505b9b81984d51b5062c27d6776120.png

那有什么办法可以证明 临时变量 的存在呢? 大家看下面的代码:

int test()
{
    int n=0;
    n++;
    return n;
}
int main()
{
    int& a=test();
}

大家觉得上面这段代码 编译器能编译通过嘛? 大家试过应该知道这里是会报错的 正确的代码应该是这样的:

int test()
{
    int n=0;
    n++;
    return n;
}
int main()
{
   const int& a=test();
}

这样我们的编译器才不会报错 也就暗示我们传返回值回来的时候 产生的临时变量是常性的(也就是被const修饰的)

那如果是这样呢?

int& test()
{
    int n=0;
    n++;
    return n;
}
int main()
{
    int& a=test();
}

我们这里使用传引用返回又是什么意思呢 ?

       我们既然返回的是一个引用 那这个引用是谁的引用呢 我们这里写得是 return n 不就是返回n的引用嘛 那既然我返回的是 n 的引用(返回n的别名) 我们用 int& a 来接收 这样我们不就得 a不就是 返回来的别名的别名了嘛  意思就是我们得 a 是n的别名的别名  那这样想我们的a不就是n的别名了嘛

我们来验证一下吧:

77f085001ce9404c9575b5174c659cd4.png

 这样不就表明我们的 a是n的别名了嘛   那大家现在觉得我们的传引用返回和传值返回的区别是什么


很显然 我们的传值返回 是会产生一个临时变量的 这个临时变量具有常性 而我们的传引用返回不会 它会直接返回返回的变量的别名

所以: 我们的传引用返回是不需要拷贝的

     但是我们上面的代码还是有问题的 如果大家有了解过栈帧的创建与销毁的话 大家就知道我们的一个函数在执行它的功能后就会返回上一层函数 与此同时这个函数里面为临时变量分配的空间就会还给操作系统 那我们这里写的代码肯定也是会那样的 所以当我们返回引用后 a的地址 就不能再去访问了 因为这块空间因为 n 所在函数栈帧的销毁而返回给操作系统了  此时如果在访问 就是越界的问题了

b5ff1acacbec488fb5aa032a883699ac.png

我们第一次去调用 没问题 而后面两次出现了随机数的情况  是因为我们第一次使用 cout 从流里面读取数据时 我们首先是要先传参的 参数就是我们的  a  而这个时候我们去访问那片空间值还是正确的 因为这片空间还没有被清理 修改 或者 覆盖 那么此时访问这片空间得到的值就还时正确的 但是后面我们传完参之后 调用 cout (这个也是一个函数) 也会有一片自己的空间 此时这篇空间就继续使用test函数用完后的空间  这是这里的空间就被覆盖使用了 里面的数据也就跟随着修改了所以后面两次调用也就时随机的值了


总结:如果函数返回时,出了函数的作用域,如果返回对象还在(还没还给我们的操作系统),那么就可以使用引用返回,如果已经返回给系统了,那么就必须使用传值返回 

目录
相关文章
|
2月前
|
C++
C++ 语言异常处理实战:在编程潮流中坚守稳定,开启代码可靠之旅
【8月更文挑战第22天】C++的异常处理机制是确保程序稳定的关键特性。它允许程序在遇到错误时优雅地响应而非直接崩溃。通过`throw`抛出异常,并用`catch`捕获处理,可使程序控制流跳转至错误处理代码。例如,在进行除法运算或文件读取时,若发生除数为零或文件无法打开等错误,则可通过抛出异常并在调用处捕获来妥善处理这些情况。恰当使用异常处理能显著提升程序的健壮性和维护性。
51 2
|
2月前
|
算法 C语言 C++
C++语言学习指南:从新手到高手,一文带你领略系统编程的巅峰技艺!
【8月更文挑战第22天】C++由Bjarne Stroustrup于1985年创立,凭借卓越性能与灵活性,在系统编程、游戏开发等领域占据重要地位。它继承了C语言的高效性,并引入面向对象编程,使代码更模块化易管理。C++支持基本语法如变量声明与控制结构;通过`iostream`库实现输入输出;利用类与对象实现面向对象编程;提供模板增强代码复用性;具备异常处理机制确保程序健壮性;C++11引入现代化特性简化编程;标准模板库(STL)支持高效编程;多线程支持利用多核优势。虽然学习曲线陡峭,但掌握后可开启高性能编程大门。随着新标准如C++20的发展,C++持续演进,提供更多开发可能性。
49 0
|
10天前
|
存储 算法 C++
C++提高篇:泛型编程和STL技术详解,探讨C++更深层的使用
文章详细探讨了C++中的泛型编程与STL技术,重点讲解了如何使用模板来创建通用的函数和类,以及模板在提高代码复用性和灵活性方面的作用。
27 2
C++提高篇:泛型编程和STL技术详解,探讨C++更深层的使用
|
2天前
|
程序员 C++
C++编程:While与For循环的流程控制全解析
总结而言,`while`循环和 `for`循环各有千秋,它们在C++编程中扮演着重要的角色。选择哪一种循环结构应根据具体的应用场景、循环逻辑的复杂性以及个人的编程风格偏好来决定。理解这些循环结构的内在机制和它们之间的差异,对于编写高效、易于维护的代码至关重要。
9 1
|
1月前
|
编译器 Linux C语言
C++基础入门
C++基础入门
|
2月前
|
Rust 安全 C++
系统编程的未来之战:Rust能否撼动C++的王座?
【8月更文挑战第31天】Rust与C++:现代系统编程的新选择。C++长期主导系统编程,但内存安全问题频发。Rust以安全性为核心,通过所有权和生命周期概念避免内存泄漏和野指针等问题。Rust在编译时确保内存安全,简化并发编程,其生态系统虽不及C++成熟,但发展迅速,为现代系统编程提供了新选择。未来有望看到更多Rust驱动的系统级应用。
46 1
|
21天前
|
程序员 C++ 容器
C++编程基础:命名空间、输入输出与默认参数
命名空间、输入输出和函数默认参数是C++编程中的基础概念。合理地使用这些特性能够使代码更加清晰、模块化和易于管理。理解并掌握这些基础知识,对于每一个C++程序员来说都是非常重要的。通过上述介绍和示例,希望能够帮助你更好地理解和运用这些C++的基础特性。
33 0
|
2月前
|
安全 编译器 程序员
【C++初阶】C++简单入门
【C++初阶】C++简单入门
|
2月前
|
安全 编译器 C++
C++入门 | 函数重载、引用、内联函数
C++入门 | 函数重载、引用、内联函数
27 5
|
2月前
|
存储 安全 编译器
C++入门 | auto关键字、范围for、指针空值nullptr
C++入门 | auto关键字、范围for、指针空值nullptr
51 4
下一篇
无影云桌面