再论传值和传址

           为什么“再”呢?哈哈~ 闲话少叙,上代码:


#include<iostream>
using namespace std;
void swap_a(int a, int b)
{
	int temp = a;
	a = b;
	b = temp;
}
void swap_b(int* a, int* b)
{
	int temp = *a;
	*a = *b;
	*b = temp;
}
void swap_c(int& a, int& b)
{
	int temp = a;
	a = b;
	b = temp;
}
int main()
{
	int x(10), y(11);
	swap_a(x, y);
	cout<<"x="<<x<<" "<<"y="<<y<<endl;
	swap_b(&x, &y);
	cout<<"x="<<x<<" "<<"y="<<y<<endl;
	swap_c(x, y);
	cout<<"x="<<x<<" "<<"y="<<y<<endl;
	return 0;
}
这是我们最熟悉的3个swap函数,分别为传值,传址和传引用,输出结果大家肯定都很清楚:第一个没有交换成功,第二个和第三个交换成功。

现在只分析前两个,传值和传址:

1、传值为何没有交换成功?大家肯定都知道,因为传递参数时生成了两个临时变量a、b,同时将x、y的值赋值给a、b,a、b在函数体内完成了交换,x、y没有任何变化。

2、传址为何成功了那?因为传递的是x、y的地址。

这是我们大家都熟悉的一种解释,那么传址函数在传递过程中就有没有生成临时变量吗?

答案是肯定的。这就产生了一个疑问,同样都产生了临时变量,为什么传址交换成功了?

下面分析一下传址过程:

在传址过程中生成了两个临时的指针变量a、b,a、b里分别存储x、y的地址。能成功的关键在于:

int temp = *a;
*a = *b;
*b = temp;

在这三行核心代码中,通过“*”对a、b中存储的地址对应的值进行了解引用。*a、*b实际是在通过x、y的地址操纵x、y实际的值,最终成功完成了交换。

好了,问题交代清楚。那么看下一个代码:

#include<iostream>
#include<stdlib.h>
using namespace std;
void haha(char* p)
{
	p = (char*) malloc(10);
}
int main()
{
	char* p = NULL;
	haha(p);
	if(p != NULL)
	{
		cout<<"p is initial"<<endl;
	}
	else
	{
		cout<<"p is NULL"<<endl;
	}
	return 0;
}
函数haha()是否帮助p完成分配内存初始化了呢?根据前面的分析,p显然为完成初化,从实质上来看p只是完成了传值。要想真正完成内存分配,可以采用以下两种方法:

1)将p的地址传入;

2)在原函数基础上,返回p值。

问题到此,还未结束,我们来探讨一下类的new操作符,上代码:

#include<iostream>
#include<stdlib.h>
using namespace std;
class Test
{
	public:
		void f()
		{
			cout<<"i am test"<<endl;
		}
};
void hehe(Test* p)
{
	p = new Test;
}
int main()
{
	Test* p;
	hehe(p);
	p->f();
	return 0;
}

p->f()能调用成功吗?按照前面的思路,当然不能,因为p未完成初始化,所以不能调用。果真如此吗?编译-运行 啊偶~~ 正常输出“i am test”~ why?

想起来啦,类的函数不属于对象的一部分,可以随时通过指针来调用,也就是没有没有hehe()函数也能完成调用。即下面代码依然可以通过运行:

Test* p;
p->f();

所以,这个例子实际上并未与我们之前对传址的解释相违背,看如下例子:

#include<iostream>
#include<stdlib.h>
using namespace std;
class Test
{
	public:
		void f()
		{
			cout<<"i am test"<<endl;
		}
		int set_a(int x)
		{
			a = x;
		}
	private:
		int a;
};
void hehe(Test* p)
{
	p = new Test;
	p->set_a(5);
}
int main()
{
	Test* p;
	hehe(p);
	p->f();
	cout<<p->set_a(10)<<endl;//error
	return 0;
}
由于p未初始化,造成了编译错误。

总结一下,在使用传址时,问一下自己到底是在传值还是在传址,通过解引用操作才能达到真正的传址。


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值