c++ 函数的值传递,引用传递 和 引用返回的探索

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

前言

C++的函数参数和返回分为按值传递和按引用传递,应用到类上面,会涉及到类的 赋值操作 复制函数 构造函数 析构函数

虽然java开发了两年,但对我而言c++我还只是一个初学者.c++还有很多陌生的特性需要自己亲自探索.这里用实际例子作为探索,不对之处望斧正:

由于基本类型和类在函数里的生命周期是相似的,这里以一个自定义类为例,一是为了方便观察对象的地址,二是可以了解每一步会涉及到类的哪些生命周期:

类的定义

#include <iostream>using std::cout;
using std::endl;
using std::string;class A {
public:A() {cout << "构造函数:" << this << endl;}A(const A &input) {cout << "复制函数:" << this << endl;}// 复制直接返回 *this 本身A &operator=(const A &input) {cout << "赋值函数:" << this << endl;// this 其实是个新的内存空间,啥值都没设置return *this;}~A() {cout << "析构函数:" << this << endl;}
};

值传递 和 返回值

我们定义一个值传递的函数,返回的也是值

A test1(A a) {cout << "test1函数体:&a=" << &a << endl;return a;
}

执行main函数如下

int main() {cout << "--- 对象创建 ---" << endl;A a;cout << "--- 函数调用 ---" << endl;A b = test1(a);cout << "--- 结束 ---" << endl;return 0;
}

执行结果

--- 对象创建 ---
构造函数:0x7fff5ed19768
--- 函数调用 ---
复制函数:0x7fff5ed19750
test1函数体:&a=0x7fff5ed19750
复制函数:0x7fff5ed19758
析构函数:0x7fff5ed19750
--- 结束 ---
析构函数:0x7fff5ed19758
析构函数:0x7fff5ed19768

由此可见,在函数的栈帧里,对入参a进行了一次复制(0x7fff5ed19750),而在返回栈帧里的input时,又会对函数结果复制生成一个临时变量(0x7fff5ed19758),并回收栈帧里的input. 函数结束会把临时变量返回给b,至此结束函数调用.也就是说,这里函数的入参和返回各涉及一次复制操作

函数入参和返回使用引用

我们对test1做出修改,将入参和返回变更为引用,如下

A &test1(A &a) {cout << "test1函数体:&a=" << &a << endl;return a;
}

将main中的b也变更为引用如下:

int main() {cout << "--- 对象创建 ---" << endl;A a;cout << "--- 函数调用 ---" << endl;A &b = test1(a);cout << "--- 结束 ---" << endl;return 0;
}

执行结果:

--- 对象创建 ---
构造函数:0x7fff56dd5768
--- 函数调用 ---
test1函数体:&a=0x7fff56dd5768
--- 结束 ---
析构函数:0x7fff56dd5768

因为是引用函数栈帧内并没有进行任何复制操作

函数返回的临时变量探索

如果函数不返回引用,或b不是引用,仍然会产生临时变量

A test1(A &a) {cout << "test1函数体:&a=" << &a << endl;return a;
}
A& test2(A &a) {cout << "test2函数体:&a=" << &a << endl;return a;
}
int main() {cout << "--- 对象创建 ---" << endl;A a;cout << "--- 函数调用1 ---" << endl;A b1 = test1(a);cout << "--- 函数调用2 ---" << endl;A b2 = test2(a);cout << "--- 结束 ---" << endl;return 0;
}

返回结果如下

--- 对象创建 ---
构造函数:0x7fff5daae758
--- 函数调用1 ---
test1函数体:&a=0x7fff5daae758
复制函数:0x7fff5daae748
--- 函数调用2 ---
test2函数体:&a=0x7fff5daae758
复制函数:0x7fff5daae740
--- 结束 ---
析构函数:0x7fff5daae740
析构函数:0x7fff5daae748
析构函数:0x7fff5daae758

test1和test2的区别只在于返回结果是否为引用,但在栈帧外都产生了临时变量

赋值操作探索

这里再对赋值做探索,这次把以上3中情况合在一起为例,如下

A &test1(A &a) {cout << "test1函数体:&a=" << &a << endl;return a;
}
A &test2(A a) {cout << "test2函数体:&a=" << &a << endl;return a;
}
A test3(A a) {cout << "test2函数体:&a=" << &a << endl;return a;
}
int main() {cout << "--- 对象创建 ---" << endl;A a;cout << "--- 函数调用1 ---" << endl;a = test1(a);cout << "--- 函数调用2 ---" << endl;a = test2(a);cout << "--- 函数调用3 ---" << endl;a = test3(a);cout << "--- 结束 ---" << endl;return 0;
}

输出结果

--- 对象创建 ---
构造函数:0x7fff513b6748
--- 函数调用1 ---
test1函数体:&a=0x7fff513b6748
赋值函数:0x7fff513b6748
--- 函数调用2 ---
复制函数:0x7fff513b6738
test2函数体:&a=0x7fff513b6738
赋值函数:0x7fff513b6748
析构函数:0x7fff513b6738
--- 函数调用3 ---
复制函数:0x7fff513b6728
test2函数体:&a=0x7fff513b6728
复制函数:0x7fff513b6730
赋值函数:0x7fff513b6748
析构函数:0x7fff513b6730
析构函数:0x7fff513b6728
--- 结束 ---
析构函数:0x7fff513b6748
  • test1 相当于a=a;除了将值赋值给自己外栈帧没有额外操作,这个很好理解
  • test2 对入参进行复制,并把复制的入参值赋值给a并在函数栈帧结束后回收入参
  • test3 比较复杂,会复制入参和临时变量,并把临时变量赋值给a,赋值结束后对入参和临时变量进行回收

转载于:https://my.oschina.net/tdONEmadao/blog/915677

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/258521.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

GCD的部分总结

GCD是基于C语言的底层API,用Block定义任务用起来非常灵活便捷. GCD的基本思想是就将操作放在队列中去执行 (1)操作使用Blocks定义(2)队列负责调度任务执行所在的线程以及具体的执行时间(3)队列的特点是先进先出(FIFO)的&#xff0c;新添加至对列的操作都会排在队尾关于多线程的…

多线程编程2-NSOperation

本文目录 前言一、NSInvocationOperation二、NSBlockOperation三、NSOperation的其他用法四、自定义NSOperation回到顶部前言 1.上一讲简单介绍了NSThread的使用&#xff0c;虽然也可以实现多线程编程&#xff0c;但是需要我们去管理线程的生命周期&#xff0c;还要考虑线程同步…

闪回表操作语法+使用闪回删除

闪回表操作语法 flashback table 【 schema.】 table_name to {【before drop 【rename to new_table_name】 】|【scn | timestamp 】】 expr 【enable | disable 】 triggers}: 参数说明&#xff1a; schema&#xff1a;用户模式 before drop&#xff1a;表示恢复到删除…

欧拉函数 - HDU1286

欧拉函数的作用&#xff1a; 有[1,2.....n]这样一个集合&#xff0c;f(n)这个集合中与n互质的元素的个数。欧拉函数描述了一些列与这个f(n)有关的一些性质&#xff0c;如下&#xff1a; 1、令p为一个素数&#xff0c;n p ^ k&#xff0c;则 f(n) p ^ k - p ^ (k-1) 2、令m&…

其中一个页签慢_渭南提升一个大专学历的有效方法

渭南提升一个大专学历的有效方法&#xff0c;宏德教育&#xff0c;目前已形成以高等学历教育为特色王牌&#xff0c;职称考评、企业内训为辅助的强力优势品牌。渭南提升一个大专学历的有效方法&#xff0c; 获得发明专利或实用新型专利&#xff0c;且已实施取得效益。出版本专业…

《收集苹果》 动态规划入门

问题描写叙述 平面上有N*M个格子&#xff0c;每一个格子中放着一定数量的苹果。你从左上角的格子開始&#xff0c;每一步仅仅能向下走或是向右走&#xff0c;每次走到一个格子上就把格子里的苹果收集起来&#xff0c;这样下去&#xff0c;你最多能收集到多少个苹果。 输入&…

Xamarin XAML语言教程通过ProgressTo方法对进度条设置

2019独角兽企业重金招聘Python工程师标准>>> Xamarin XAML语言教程通过ProgressTo方法对进度条设置 在ProgressBar中定义了一个ProgressTo方法&#xff0c;此方法也可以用来对进度条当前的进行进行设置&#xff0c;ProgressTo与Progress属性的不同之处在于ProgressT…

h5新特性

 CSDN博客 Gane_ChengHTML5新特性浅谈 发表于2016/10/17 21:25:58 7809人阅读 分类&#xff1a; 前端 转载请注明出处&#xff1a; http://blog.csdn.net/gane_cheng/article/details/52819118 http://www.ganecheng.tech/blog/52819118.html &#xff08;浏览效果更好…

mysql日期截取年月_摄影大赛丨“我遇见最美的光”第五届全国医务人员摄影大展 截稿日期2020年8月15日...

截稿日期2020年8月15日《“我遇见最美的光”第五届全国医务人员摄影大展》欣赏过山川壮丽&#xff0c;瞻仰过造化旖旎&#xff0c;敬重于生命伟大&#xff0c;感动于英雄凯旋……由《大众摄影》主办&#xff0c;正大天晴药业集团股份有限公司、《中国卫生影像》杂志协办的“我遇…

Pytorch的C++接口实践

Pytorch1.1版本已经提供了相对稳定的c接口&#xff0c;网上也有了众多的资料供大家参考&#xff0c;进行c的接口的初步尝试。 可以按照对应的选项下载&#xff0c;下面我们要说的是&#xff1a; 如何利用已经编译好的官方libtorch库和其他的opencv库等联合编写应用&#xff1f…

HttpClient v4.5 简单抓取主页数据

由于工作原因&#xff0c;需要每隔半小时刷新一些网页&#xff0c;并查看上面的数据是否有更新。这件事能否自动化进行呢&#xff1f;查找了下Java相关的资料&#xff0c;蹦出一个关键词&#xff1a;HttpClient。 HttpClient是常用Http客户端库&#xff0c;相关的资料也不少&am…

matlab局部放大的图中图画法

【亲测有效】 在作图过程中&#xff0c;如果想将局部信息展示出来并且画在同一张图中&#xff0c;一般的MATLAB作图法就比较拙计了&#xff0c;好在MATLAB还是很强大的&#xff0c;当然&#xff0c;除了不能当女朋友之外 .... ╮(╯▽╰)╭ function showdetail()% 在当前的ax…

【2020年】最新中国科学院大学学位论文写作规范

最近在完成国科大博士论文写作的时候&#xff0c;有一些心得体会&#xff0c;特此总结下来&#xff0c;以飨读者&#xff0c;尤其是可爱的学弟学妹们。需要注意的是&#xff0c; 以下仅仅是我自己的心得而已&#xff0c;仅供参考。 1. 首先推荐大家使用国科大的Latex模板&…

用fft对信号进行频谱分析实验报告_示波器上的频域分析利器,Spectrum View测试分析...

简介&#xff1a;【Spectrum View技术文章系列】从基础篇开始&#xff0c;讲述利用示波器上的Spectrum View功能观测多通道信号频谱分析正文&#xff1a;示波器和频谱仪都是电子测试测量中必不可少的测试设备&#xff0c;分别用于观察信号的时域波形和频谱。时域波形是信号最原…

复盘caffe安装

最近因之前的服务器上的caffe奔溃了&#xff0c;不得已重新安装这一古老的深度学习框架&#xff0c;之前也尝试了好几次&#xff0c;每次都失败&#xff0c;这次总算是成功了&#xff0c;因此及时地总结一下。 以下安装的caffe主要是针对之前虹膜分割和巩膜分割所需的caffe版本…

HP P2000 RAID-5两块盘离线的数据恢复报告

1. 故障描述本案例是HP P2000的存储vmware exsi虚拟化平台&#xff0c;由RAID-5由10块lT硬盘组成&#xff0c;其中6号盘是热备盘&#xff0c;由于故障导致RAID-5磁盘阵列的两块盘掉线&#xff0c;表现为两块硬盘亮黄灯。 经用户方维护人员检测&#xff0c;故障硬盘应为物理故障…

为什么torch.nn.Linear的表达形式为y=xA^T+b而不是常见的y=Ax+b?

今天看代码&#xff0c;对比了常见的公式表达与代码的表达&#xff0c;发觉torch.nn.Linear的数学表达与我想象的有点不同&#xff0c;于是思索了一番。 众多周知&#xff0c;torch.nn.Linear作为全连接层&#xff0c;将下一层的每个结点与上一层的每一节点相连&#xff0c;用…

Leetcode47: Palindrome Linked List

Given a singly linked list, determine if it is a palindrome. 推断一个链表是不是回文的&#xff0c;一个比較简单的办法是把链表每一个结点的值存在vector里。然后首尾比較。时间复杂度O(n)。空间复杂度O(n)。 /*** Definition for singly-linked list.* struct ListNode {…

【转】七个例子帮你更好地理解 CPU 缓存

我的大多数读者都知道缓存是一种快速、小型、存储最近已访问的内存的地方。这个描述相当准确&#xff0c;但是深入处理器缓存如何工作的“枯燥”细节&#xff0c;会对尝试理解程序性能有很大帮助。在这篇博文中&#xff0c;我将通过示例代码来说明缓存是如何工作的&#xff0c;…

win10 平台VS2019最简安装实现C++/C开发

这两天一直在安装vs2015,总是卡在visual studio 2015 出现安装包丢失或损坏的现象&#xff0c;尽管按照网上很多方法尝试解决&#xff0c;但是一直不行。算了。还是使用最新版的VS 2019安装&#xff0c;没想到很顺利。 下面总结一下在win10平台上最简安装VS2019&#xff0c;实…