前言:
最近对内存产生了兴趣、全是因为马士兵老师的一句Master key、马上要考二级了、大题构造函数比较多、形参有 int & x 这么写的、也有int *x 这么写的、还有普通 int x这么写的、我的乖乖这都是传的什么?
int x 是 传值、int *x 是传址、 int & x是传引用、那这三者传参数都有什么区别呢?
下面就用三个例子讲解
声明:下面堆栈的图其实是不正确的、八个基本类型(byte、short、int、long、char、float、double、boolean)都是在栈里面的、而下面的int型我把名字看做栈里面、里面的数值看做是堆里面的、只是为了大家明白传值、址、引用、的区别。
<span style="font-size:18px;">// C_TEST.cpp : Defines the entry point for the console application. // // #include "stdafx.h" #include "iostream" using namespace std;//我是在VS2008里面作的调试,这里需要导入命名空间STD </span>
传值
<span style="font-size:18px;">//传值 void swap1(int x,int y) { X = 3 Y = 4 cout<<" 传值函数输出: "<<x<<" "<<y<<endl; } void main()//入口点 { int a(1); int b(2); swap1(a,b); cout<<" 外界值: "<<a<<" "<<b<<endl; } //输出: //传值函数输出:3 4 //外界值: 1 2 </span>
堆栈图(执行swap1前、执行swap1后)
是把实参的值赋值给行参
、那么对行参的修改,不会影响实参的值
。
简单的说就是、栈里面的地址、堆里面的对象都不是一个、比如我有首《chenchen绝唱》这首歌、我拷给了我的好同桌许小乖、她觉得特难听、立马就删了、她删了歌、我这还有、互不影响、还有一点要说明的就是、栈里存放着指向对象的地址、所以对象复制出来是一样的、但是堆里的地址不一样、所以ab栈的地址与xy栈的地址不一样、就好似我的歌放在我的硬盘里、考给同桌的歌放在她的硬盘里、物理地址不一样。
传址
这里把x、y做了交换、因为是传址、所以更改了a 、b指向堆里面的对象。
//传址 void swap2(int *x,int *y) //传址调用 { //把主函数里数据的地址传了过来 //这里改变了数据的地址,在主函数里打印出a,b的时候,当然就发生了交换! int temp; temp = *x; *x = *y; *y = temp; cout<<" 传址函数内: "<<x<<" "<<y<<endl; } void main()//入口点 { int a(1); int b(2); swap2(&a,&b); cout<<" 外界值: "<<a<<" "<<b<<endl; } //输出: //传址函数输出:0016FE04 0016FDF8 //外界值: 2 1
这里打印了x y 是 内存 地址、交换操作却是对堆里对象的操作。
堆栈图(执行swap2前、执行swap2后)
是传值的一种特殊方式,只是他传递的是地址,不是普通的如int
那么传地址以后,实参和行参都指向同一个对象
对x、y的操作、互换、其实就是对a、b值的互换、因为他们都指向同一个对象、打个比方、有两张一模一样的藏宝图、你一张、我一张、但是宝藏只有一个、我找到宝藏、拿走了、你再过去拿宝藏就没有了、所以传址只是把地址传过来、用的对象还是那个对象、所以x y值的互换就是 对象 1 和2 值的互换、但是ab的指向的地址没变、堆里两个对象的值却互换了。
传引用
<span style="font-size:18px;">//引用 void swap3(int &x,int &y)//传引用 { //加了&之后,用地址引用了主函数里面的数据值,说明x,y 的地址是a,b的地址~~,因而主函数里面的a,b发生交换~~ int temp; temp = x; x = y; y = temp; cout<<" 换址函数内: "<<x<<" "<<y<<endl; } void main()//入口点 { int a(1); int b(2); swap3(a,b); cout<<" 外界值: "<<a<<" "<<b<<endl; } //输出: //传址函数输出:21 //外界值: 2 1 </span>
堆栈图(执行swap3前、执行swap3后)
这里的图有可能不太对、但是我能这么理解了、打个比方吧、一人拿着一张藏宝图叫我去找宝藏、藏宝图给了我、我去把宝藏拿给他、上图栈里的x y应该是指向a b 或者是a b的别名。
-----------------------------------------------------------------------------------
函数调用角度SEE
传值:
传值:
函数参数压栈的是参数的副本。
任何的修改是在副本上作用,没有作用在原来的变量上。
传指针:
压栈的是指针变量的副本。
当你对指针解指针操作时,其值是指向原来的那个变量,所以对原来变量操作。
传引用:
压栈的是引用的副本。由于引用是指向某个变量的,对引用的操作其实就是对他指向的变量的操作。(作用 和传指针一样,只是引用少了解指针的草纸)
-----------------------------------------------------------------------------------
总结:
这两天学了内存发现挺有意思的、说是换真还是一头雾水、不是特别清楚、但是感觉真的对分析程序很有帮助、基础知识嘛、要好好学。
参考文章
http://blog.csdn.net/juliababy/article/details/2837646
http://blog.csdn.net/aristolto/article/details/7262738
——————————————— 困-困 ———————————————
——————————chenchen——————————