C++之值传递&指针传递&引用传递详解
C++之值传递&指针传递&引用传递详解
1.函数基础
一个函数由以下四部分组成:
返回类型
函数名
参数
(0个或多个)函数体
其中,函数的参数叫做形参
,函数执行的操作的语句块叫做函数体
2.值传递
像一个这样swap函数,调用的时候,会用实参
初始化swap函数对应的形参
void Swap(int a, int b)
{
int tmp = a;
a = b;
b = tmp;
}
在内存中会拷贝一份实参的值,但是修改形参的值并不影响实参的值
- 测试用例
#include <iostream>
void Swap(int a, int b)
{
int tmp = a;
a = b;
b = tmp;
}
int main()
{
int n = 0;
int i = 1024;
Swap(n, i);
std::cout << "n: " << n << "\ni: " << i << std::endl;
// 运行结果
// n: 0
// i: 1024
return 0;
}
int n = 0;
int i = n; // i是n的值的副本
i = 42;
3.指针传递
指针的行为和其他非引用类型一样。当执行指针拷贝操作时,拷贝的是指针的值。
拷贝之后,两个指针是不同的指针。因为指针使我们可以间接地访问它所指的对象,所以通过指针可以修改它所指对象的值
void SwapPoniter(int *a, int *b)
{
int tmp = *a;
*a = *b;
*b = tmp;
}
- 测试用例
#include <iostream>
void SwapPoniter(int *a, int *b)
{
int tmp = *a;
*a = *b;
*b = tmp; // 修改了指针b指向的对象的值
b = 0; // 只改变了函数体中的内存拷贝,实参并没有被修改
}
int main()
{
int n = 0;
int i = 1024;
int *j = &n;
int *k = &i;
SwapPoniter(j, k);
std::cout << "j: " << *j << "\nk: " << *k << std::endl;
// 运行结果
// j: 1024
// k: 0
return 0;
}
int n = 0, i = 1024;
int *p = &n, *q = &i; // p指向n;q指向i
*p = 1024; // n的值被修改;p不变
p = q; // p现在指向了i;但是n与i的值都不变
传递指针,就是拷贝一个指针,它储存的值是一样的,解引用后是指向同一个对象,但是修改指针的值就是修改拷贝对象的值
在C语言中,大多数程序员都用得指针类型的形参去访问函数的外部对象,在C++中,建议使用引用类型的形参代替指针
4.引用传递
引用传递跟指针传递有点类似,使用引用传参,允许函数访问,改变一个或多个实参的值
void SwapQuote(int &a, int &b)
{
int tmp = a;
a = b;
b = tmp;
}
- 测试用例
#include <iostream>
void SwapQuote(int &a, int &b)
{
int tmp = a;
a = b;
b = tmp;
}
int main()
{
int n = 0;
int i = 1024;
SwapQuote(n, i);
std::cout << "n: " << n << "\ni: " << i << std::endl;
// 运行结果
// n: 1024
// i: 0
return 0;
}
- 使用引用传递可以避免拷贝
- 拷贝大的类类型对象或者容器对象比较低效,甚至有的类类型(包括IO类型在内)根本就不支持拷贝操作。当某种类型不支持拷贝操作时,函数只能通过引用形参访问该类型的对象。
举个例子,我们准备编写一个函数比较两个string对象的长度。因为string对象可能会非常长,所以应该尽量避免直接拷贝它们,这时使用引用形参是比较明智的选择。又因为比较长度无须改变string对象的内容,所以把形参定义成对常量的引用
- 当我们只是单纯读取实参,并不打算修改时,尽量使用常量引用
#include <iostream>
void testprint(const int &a)
{
std::cout << "a: " << a << std::endl;
}
int main()
{
int num = 111;
testprint(num);
// 输出结果 a: 111
return 0;
}
- 使用引用传递返回额外信息
一个函数只能返回一个值,然而有时函数需要同时返回多个值,引用形参为我们一次返回多个结果提供了有效的途径
举个例子, 在刚刚的swap函数增加返回最小值与最大值
void SwapQuote(int &a, int &b, int &mix, int &max)
{
int tmp = a;
a = b;
b = tmp;
a < b ? mix = a, max = b : max = a, mix = b;
}
这样我们只需要调用的时候传入实参,即可修改实参的值
今天是1024程序员的节日,enjoy it ~
C++之值传递&指针传递&引用传递详解的更多相关文章
- 【Qt】信号和槽对值传递参数和引用传递参数的总结
在同一个线程中 当信号和槽都在同一个线程中时,值传递参数和引用传递参数有区别: 值传递会复制对象:(测试时,打印传递前后的地址不同) 引用传递不会复制对象:(测试时,打印传递前后的地址相同) 不在同一 ...
- Java 为值传递而不是引用传递
——reference Java is Pass by Value and Not Pass by Reference 其实这个问题是一个非常初级的问题,相关的概念初学者早已掌握,但是时间长了还是容易 ...
- java是值传递,还是引用传递?
原文地址:http://blog.csdn.net/zxmzfbdc/article/details/5401960 java到底是值传递,还是引用传递?以前国内的java开发者有过很多争论,由于& ...
- c语言 函数传输传递的三种方式(值、指针、引用)
本文摘自<彻底搞定c指针> 一.三道考题开讲之前,我先请你做三道题目.(嘿嘿,得先把你的头脑搞昏才行……唉呀,谁扔我鸡蛋?)考题一,程序代码如下:void Exchg1(int x, in ...
- java值转递?引用传递?
值传递是传递的是原值的副本,引用传递传递的是原值. 在Java中,如果是基本数据类型,传递的是该参数字面量值的拷贝.如果是引用数据类型,传递的是该参数所引用对象在堆中地址的拷贝. swap(int a ...
- java都是值传递,没有引用传递
博主这几天在复习 javaSE 部分的内容时,遇到了关于参数传值的问题,但是始终不知道原因,上网上一查才知道钻牛角尖了,把C语言的参数传值转移到java中了. 相信很多在学习java之前,有接触过C/ ...
- java方法中只有值传递,没有引用传递
public class Example { String testString = new String("good"); char[] testCharArray = {'a' ...
- 【Java基础】11、java方法中只有值传递,没有引用传递
public class Example { String testString = new String("good"); char[] testCharArray = {'a' ...
- PHP引用(&)使用详解
初学php关于&引用 官方文档: 1.引用是什么:http://www.php.net/manual/zh/language.references.whatare.php 2.引用做什么:ht ...
- C++ 引用 & 的详解
转载来自:CSDNinsistGoGo (http://blog.csdn.net/insistgogo/article/details/6655077) 引用的应用: 常引用: 语法: const ...
随机推荐
- 大数据管理系统架构Hadoop
Hadoop 起源于Google Lab开发的Google File System (GFS)存储系统和MapReduce数据处理框架.2008年,Hadoop成了Apache上的顶级项目,发展到今天 ...
- Min GW 安装教程(转载)
下载方式一:1.百度搜索关键词"mingw",点击第一个:2.进入官网后,点击右上角的"Downloads":3.进入第三个页面后,点击"mingw- ...
- javaScript 事件循环机制
JavaScript是单线程的编程语言,只能同一时间内做一件事.但是在遇到异步事件的时候,js线程并没有阻塞,还会继续执行,这就是因为JS有事件循环机制. 事件循环流程总结 主线程开始执行一段代码, ...
- 元数据治理利器 - Apache Atlas
一.功能简介 Atlas 是一组可扩展的核心基础治理服务,使企业能够高效地满足其在 Hadoop 中的合规性要求,并允许与整个企业数据生态系统集成.Apache Atlas 为组织提供开放的元数据管理 ...
- js--自定义对象
1.直接量对象(JSON) {"name":"zhangsan","age":25} {}代表一个对象,包含多组键值对. 通常key是字符串 ...
- ceph 009 管理定义crushmap 故障域
管理和自定义crushmap 定义pg到osd的映射关系 通过crush算法使三副本映射到理想的主机或者机架 更改故障域提高可靠性 pg到osd映射由crush实现 下载时需要将对象从osd搜索到,组 ...
- which 和 that 在定语从句中作介词宾语的用法
关系代词在定语从句中作介词的宾语,且介词在关系代词之前时,关系代词应该用 which:介词在定语从句句末,关系代词可以用 that 或 which. (一)He teaches in a school ...
- C#/VB.NET 创建PDF/UA文件
1.什么是PDF/UA文件 PDF/UA,即Universally Accessible PDF,该格式的PDF文件是于2012年8月以ISO标准14289-1发布的.具有普遍可访问的PDF文档标准. ...
- CF453C Little Pony and Summer Sun Celebration(构造、贪心(?))
CF453C Little Pony and Summer Sun Celebration 题解 这道题要求输出任意解,并且路径长度不超过4n就行,所以给了我们乱搞构造的机会. 我这里给出一种构造思路 ...
- qt unknown type name编译报错记录
在classA中include class B,然后定义成员变量的时候,报错unknown type name了. 一共有两种可能造成这种问题: 1.circle include,同时在classA中 ...