首先,感谢http://www.cnblogs.com/jacktag/p/3173415.html我们的定义为值传递是传递栈中的值;引用传递是传递栈地址。
注意,引用传递不是传递堆中的地址,而是传递堆栈中的地址。
1、java
在互联网上,大部分认为java是按值传递的。这样的说法不能说是错误的。但是更深层次的理解是,对于java而言,堆栈上只能分配基本类型的存储和对对象的引用。而所有对象的创建均存在与堆上,堆栈中保存对该对象的引用。在函数传值时,对于基本类型,肯定是通过压栈数据值得方式进行传递,对于引用,同样是通过压栈引用的方式进行传递。
2、c#
c#中有ref关键字,但是似乎更令大家困惑了,抄一段上面链接的代码
class Program
{
static void Main(string[] args)
{
Student xiaohong = new Student("小红", 12);
BanZheng(ref xiaohong);
//BanJiaZheng(xiaohong); //这种情况下第一种输出为红姐 18 第二种输出为小红 12
Console.WriteLine(xiaohong.Name + " " + xiaohong.Age);
Console.ReadKey();
}
static void BanZheng(ref Student student)
{
//student.Name = "红姐";
//student.Age = 18;
student = new Student("红姐", 18);
}
static void BanJiaZheng(Student student)
{
//student.Name = "红姐";
//student.Age = 18; //如果将这两句话注释掉,输出为红姐 18//
student = new Student("红姐", 18);
}
}
class Student
{
public Student(string name, int age)
{
Name = name;
Age = age;
}
public string Name { get; set; }
public int Age { get; set; }
}
如此可以看出,c#和java类似,传递对象时,如果不使用ref关键字,则是进行值传递,传递对堆中对象的引用。而如果加上ref,则相当与传递的是对引用的引用,也就是堆栈中对象的引用的堆栈地址。换句话说,加上ref和不加ref都可以对对象进行修改,但是如果不加ref,则没有办法将该引用指向新的地址,因为引用是值传递。
另外,你不能用ref或者out关键字声明变量。ref在使用时必须提前对变量赋值,而out在使用前不需要提前对变量赋值,如果有赋值,会自动清空。
3、C/C++
JAVA和纯C#(除非使用不安全代码)中都没有指针的概念。但是C/C++有。
相对于c#和java,在c++中,对象时存储在堆中还是存储在栈中,是由开发者决定的。显然,堆和栈有容量,性能,生存周期上的差异。
Object obj(int initParam);
上面语句表示根据其所在的上下文自动声明对象。
如果上面的话在函数中出现,就表示在堆栈上分配对象。