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;
  }

本站声明:
1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;

2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;

3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;

4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;

5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/tech/pnotes/294635.html

(0)
上一篇 2022年12月6日 00:25
下一篇 2022年12月6日 22:11

相关推荐

发表回复

登录后才能评论