C++之值传递&指针传递&引用传递详解

九路
• 阅读 74

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 ~

点赞
收藏
评论区
推荐文章
小果果学长 小果果学长
1年前
【编译原理】语义分析S属性定义的自下而上计算
目录一、实验目的(about:blank%E4%B8%80%E3%80%81%E5%AE%9E%E9%AA%8C%E7%9B%AE%E7%9A%84)二、实验任务(about:blank%E4%BA%8C%E3%80%81%E5%AE%9E%E9%AA%8C%E4%BB%BB%E5%8A%A1)三、实验原理(about:blank%E
阿邹 阿邹
1年前
java传值和传引用问题
这个问题还是很常见的,如果你平常敲代码比较多你可能经常会遇到这个问题。如果你知道java这个机制,你可能还会一直在找代码的问题。java中的值传递和引用传递。比如下面有这俩个方法javaprivatevoidupdataValue(Strings){s"123";}privatevoidupd
Wesley13 Wesley13
1年前
Java中只存在值传递
在Java中并不存在引用传递(即地址传递),对于变量(可以是基本数据类型,也可以是引用数据类型)而言,可以理解为就是一个地址。传递,存在着拷贝操作。举个列子:1、在方法参数上,传递的是基本数据类型。定义了一个用于交换两个整型数的方法:publicstaticvoidswap(inta,intb){in
Wesley13 Wesley13
1年前
Java里的按值传递与引用传递
按值传递还是按引用传递这个在Java里面是经常被提起的问题,也有一些争论,似乎最后还有一个所谓的结论:“在Java里面参数传递都是按值传递”。事实上,这很容易让人迷惑,下面先分别看看什么是按值传递,什么是按引用传递,只要能正确理解,至于称作按什么传递就不是个大问题了。1:按值传递是什么指的是在方法调用时,传递的参
Wesley13 Wesley13
1年前
Java到底是引用传递还是值传递
前言前段时间在群里看到类似这样一个问题,下面的代码会输出什么呢?public void test(){   String str  "hello";   change(str);   System.out.println(str);}private void change(String str){  
Stella981 Stella981
1年前
ShellScript值传递参数
Shell传递参数摘自菜鸟教程:http://www.runoob.com/linux/linuxshellpassingarguments.html(https://www.oschina.net/action/GoToLink?urlhttp%
Wesley13 Wesley13
1年前
12、ES6形参默认值
当定义函数的时候,可以给参数设置默认值。调用的时候不传递参数值,就使用默认值。例子1:普通函数,不传递参数值。默认全是undefined。functionadd(a,b,c){console.log(a,b,c);}add();//不传递参数是,默认参数值全是undef
Wesley13 Wesley13
1年前
JAVA初学笔记&宋红康JAVA基础、高级篇(其九)
关于类与方法的使用技巧方法重载定义:同一个类中,允许多个同名方法,只需所传递的参数类型不同即可(类似于路由系统)使用:根据传递的类型自动区分到对应的方法值传递多个实参传递JDK5.0之前:publicstaticvoidtest(inta,Str
Easter79 Easter79
1年前
Swift3.0 类和结构体的选择
结构体实例总是通过值传递,类实例总是通过引用传递先说说值类型和引用类型的区别值类型被赋予给一个变量、常量或者被传递给一个函数的时候,其值会被拷贝在Swift中,所有的结构体和枚举类型都是值类型。这意味着它们的实例,以及实例中所包含的任何值类型属性,在代码中传递的时候都会被复制。引用类型在被赋予到一个变量、常
Stella981 Stella981
1年前
JavaScript深入之参数按值传递
定义在《JavaScript高级程序设计》第三版4.1.3,讲到传递参数:ECMAScript中所有函数的参数都是按值传递的。什么是按值传递呢?也就是说,把函数外部的值复制给函数内部的参数,就和把值从一个变量复制到另一个变量一样。按值传递举个简单的例子:varvalue1;fun