C++ 入门:方法调用之传值、传引用、传地址

传值

和java不同,如果不指定传引用或者传地址,方法会把实参复制一份,也就是说main函数中的变量i,和restVal方法中的入参i是两个独立的变量,它们有各自的内存地址。这种方式调用不会对原有变量造成影响。 

#include <iostream>
 
using namespace std;
 
int resetVal(int i)
{
	i = 100;
	return i;
}
 
int main(void)
{
   int i = 10, j = 20;
   cout << "before reset i:" << i << endl;
   cout << "call resetVal returned i:" << resetVal(i) << endl;
   cout << "after reset i:" << i << endl;
   return 0;
}

output:
before reset i:10
call resetVal returned i:100
after reset i:10

调用的方式和Java调用方法一样,只是参数都是实参的一个副本了,这样的调用并不会对之前的原有的i进行修改。 

传引用

刚接触有些疑惑,暂时把它当做原始变量的一个别名就好了。例如 int i = 0; int &j = i;  i和j都指向同一个内存地址,好比一个人叫王钢蛋,小名叫蛋子一样,这两个名字都是指向一个实体对象。

#include <iostream>
 
using namespace std;
 
int resetVal(int& i) // change int i => int& i 
{
	i = 100;
	return i;
}
 
int main(void)
{
   int i = 10, j = 20;
   cout << "before reset i:" << i << endl;
   cout << "call resetVal returned i:" << resetVal(i) << endl;
   cout << "after reset i:" << i << endl;
   return 0;
}

output:
before reset i:10
call resetVal returned i:100
after reset i:100

相比传值的方法,只是改了被调用方法的参数列表中的参数类型,从 int 类型改成了 int&,main函数中的调用没有任何变化。个人理解,restVal方法由参数列表可知,入参是一个引用,会自动复制,也就是说在整个调用栈中,main先入栈,创建了i,调用restVal时再入栈,创建i的别名tmp,和i指向同一内存地址。表明这是一个引用,而不是复制品。从结果可知,原始变量i已经被修改了。

传地址(传指针)

指针和引用类似,都是把内存地址传过去了。只是传递的时候需要使用求址运算符(&)把变量的地址取出来传递过去。传引用的时候不需要。接收部分需要使用解引用的方式,把指向的地址转换成具体指向的对象。

#include <iostream>
 
using namespace std;
 
int resetVal(int* i) // declare this is a pointer
{
	*i = 100;        // deRef and change value
	return *i;       // return the value , not pointer
}
 
int main(void)
{
   int i = 10, j = 20;
   cout << "before reset i:" << i << endl;
   cout << "call resetVal returned i:" << resetVal(&i) << endl; // declare pass the address of i
   cout << "after reset i:" << i << endl;
   return 0;
}

output:
before reset i:10
call resetVal returned i:100
after reset i:100

结果和传引用一样,都是修改了原始的i。

于是有了一个疑问,为什么有指针了还要用引用呢?

因为C++是从C沿袭下来的,并且需要使用操作符重载。下面有原文(原文地址):

Why does C++ have both pointers and references?

C++ inherited pointers from C, so I couldn't remove them without causing serious compatibility problems. References are useful for several things, but the direct reason I introduced them in C++ was to support operator overloading. For example:

void f1(const complex* x, const complex* y)	// without references
	{
		complex z = *x+*y;	// ugly
		// ...
	}

	void f2(const complex& x, const complex& y)	// with references
	{
		complex z = x+y;	// better
		// ...
	}	

More generally, if you want to have both the functionality of pointers and the functionality of references, you need either two different types (as in C++) or two different sets of operations on a single type. For example, with a single type you need both an operation to assign to the object referred to and an operation to assign to the reference/pointer. This can be done using separate operators (as in Simula). For example:

Ref<My_type> r :- new My_type;
	r := 7;			// assign to object
	r :- new My_type;	// assign to reference

Alternatively, you could rely on type checking (overloading).For example:

Ref<My_type> r = new My_type;
	r = 7;			// assign to object
	r = new My_type;	// assign to reference

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值