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;
}
  • 使用引用传递可以避免拷贝
  1. 拷贝大的类类型对象或者容器对象比较低效,甚至有的类类型(包括IO类型在内)根本就不支持拷贝操作。当某种类型不支持拷贝操作时,函数只能通过引用形参访问该类型的对象。

举个例子,我们准备编写一个函数比较两个string对象的长度。因为string对象可能会非常长,所以应该尽量避免直接拷贝它们,这时使用引用形参是比较明智的选择。又因为比较长度无须改变string对象的内容,所以把形参定义成对常量的引用

  1. 当我们只是单纯读取实参,并不打算修改时,尽量使用常量引用
#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++之值传递&指针传递&引用传递详解的更多相关文章

  1. 【Qt】信号和槽对值传递参数和引用传递参数的总结

    在同一个线程中 当信号和槽都在同一个线程中时,值传递参数和引用传递参数有区别: 值传递会复制对象:(测试时,打印传递前后的地址不同) 引用传递不会复制对象:(测试时,打印传递前后的地址相同) 不在同一 ...

  2. Java 为值传递而不是引用传递

    ——reference Java is Pass by Value and Not Pass by Reference 其实这个问题是一个非常初级的问题,相关的概念初学者早已掌握,但是时间长了还是容易 ...

  3. java是值传递,还是引用传递?

    原文地址:http://blog.csdn.net/zxmzfbdc/article/details/5401960  java到底是值传递,还是引用传递?以前国内的java开发者有过很多争论,由于& ...

  4. c语言 函数传输传递的三种方式(值、指针、引用)

    本文摘自<彻底搞定c指针> 一.三道考题开讲之前,我先请你做三道题目.(嘿嘿,得先把你的头脑搞昏才行……唉呀,谁扔我鸡蛋?)考题一,程序代码如下:void Exchg1(int x, in ...

  5. java值转递?引用传递?

    值传递是传递的是原值的副本,引用传递传递的是原值. 在Java中,如果是基本数据类型,传递的是该参数字面量值的拷贝.如果是引用数据类型,传递的是该参数所引用对象在堆中地址的拷贝. swap(int a ...

  6. java都是值传递,没有引用传递

    博主这几天在复习 javaSE 部分的内容时,遇到了关于参数传值的问题,但是始终不知道原因,上网上一查才知道钻牛角尖了,把C语言的参数传值转移到java中了. 相信很多在学习java之前,有接触过C/ ...

  7. java方法中只有值传递,没有引用传递

    public class Example { String testString = new String("good"); char[] testCharArray = {'a' ...

  8. 【Java基础】11、java方法中只有值传递,没有引用传递

    public class Example { String testString = new String("good"); char[] testCharArray = {'a' ...

  9. PHP引用(&)使用详解

    初学php关于&引用 官方文档: 1.引用是什么:http://www.php.net/manual/zh/language.references.whatare.php 2.引用做什么:ht ...

  10. C++ 引用 & 的详解

    转载来自:CSDNinsistGoGo  (http://blog.csdn.net/insistgogo/article/details/6655077) 引用的应用: 常引用: 语法: const ...

随机推荐

  1. P4715 淘汰赛 - 记录

    P4715 淘汰赛 题目描述 有 2^n (n≤7) 个国家参加世界杯决赛圈且进入淘汰赛环节.我经知道各个国家的能力值,且都不相等.能力值高的国家和能力值低的国家踢比赛时高者获胜.1 号国家和 2 号 ...

  2. Vue3系列11--Teleport传送组件

    Teleport 是一种能够将我们的模板移动到 DOM 中 Vue app 之外的其他位置的技术,不受父级style.v-show等属性影响,但data.prop数据依旧能够共用的技术:类似于 Rea ...

  3. java-分支结构(四种基本分支结构的认识)

    分支结构:有条件的执行某语句,并非每句必走 1)if结构:1条路 2)if...else结构:2条路 3)if...else if结构:多条路 4)switch...case结构:多条路 优点:效率高 ...

  4. Shell 脚本报错 line x: [xxx: command not found

    [root@VM-0-6-centos sh_scripts]# bash val.sh username: hello world! val.sh: line 5: [hello: command ...

  5. 青源Talk第8期|苗旺:因果推断,观察性研究和2021年诺贝尔经济学奖

    biobank 英国的基金数据因果推断和不同的研究互相论证,而非一个研究得到的接了就行.数据融合,data fusion,同一个因果问题不同数据不同结论,以及历史上的数据,来共同得到更稳健.更高效的推 ...

  6. Spring 16: SM(Spring + MyBatis) 注解式事务 与 声明式事务

    Spring事务处理方式 方式1:注解式事务 使用@Transactional注解完成事务控制,此注解可添加到类上,则对类中所有方法执行事务的设定,注解添加到方法上,则对该方法执行事务处理 @Tran ...

  7. 大家都能看得懂的源码 - 那些关于DOM的常见Hook封装(二)

    本文是深入浅出 ahooks 源码系列文章的第十五篇,该系列已整理成文档-地址.觉得还不错,给个 star 支持一下哈,Thanks. 本篇接着针对关于 DOM 的各个 Hook 封装进行解读. us ...

  8. C#使用BouncyCastle生成PKCS#12数字证书

    背景 生成数字证书用于PDF文档数字签名 数字证书需要考虑环境兼容性,如linux.windows 网上资料不全或版本多样 本文章主要介绍了在C#中使用BouncyCastle生成PKCS#12个人信 ...

  9. KingbaseES V8R6C5B041 sys_backup.sh单实例备份案例

    ​ 数据库版本: test=# select version(); version ---------------------------------------------------------- ...

  10. Q准则涡识别方法

    Q准则(Q Criterion)在涡识别中计算效率高,效果也不错,是一种常用的涡提取/识别方法. 了解Q准则需要从速度梯度张量入手,而速度梯度张量可以分解成两部分 \[\frac{\partial u ...