现在学到了值类型和引用类型,有点糊涂了,现请教大家
static void Main(string [] args)
{
   int i = 123;
   object o = i;
   i = 456;
}
如果按值类型和引用类型的概念来说的话,o不是指向了i的内存地址了么,那现在i的值改变了,i的内存地址还是不变的吧?但在控制台打印出来是 i = 456;o = 123;这是为什么?还有个问题,就是正则表达式可以再任意平台使用么?我只是在JavaScript上用过,请教一下

解决方案 »

  1.   

    概念书上都有,关键是能解释明白先声明值类型i了,i自己占一个内存地址,值是123然后声明引用类型变量o,让o = i就是把o指向i了吧,那不论i的值怎么改变,o还是指向i的吧那为什么当i的值改变的时候o的值没改变呢?
      

  2.   

          int   i   =   123;
          object   o   =   i;
          i   =   456; i最终改变了它的内存地址, 故 i =456,
    对象 o 它是在  i  =  456; 之前引用i = 123的这个内存地址,它不管i 如何变化,它始终指向i  =  123这个内存地址 。o 它是引用类型, i 为值类型我是这样理解的。
      

  3.   

    o 它是引用类型, i 为值类型  让o = i就是把o指向i了吧,那不论i的值怎么改变,o还是指向i的吧   错误O 它是在i  =  456; 之前引用i  =  123这个内存地址的,它是始终引用123这个内存地址。
      

  4.   

    很简单...一句话,装箱以后,o和i没有任何关系了,i是i,o是o...3、6、7楼解释都是错的...
      

  5.   

    真要理解去看MSDN...把栈、托管堆、垃圾回收堆都要分清楚才行...弄一堆含糊不清的术语出来才是混淆视听...比如内存地址...i分配的内存地址与o分配的内存地址根本就不是两个地方,装不装箱都是一个概念...哪有以前的内存地址以后的内存地址之说...去看MSDN吧...装箱和取消装箱(C# 编程指南)
      

  6.   

    i分配的内存地址与o分配的内存地址根本就不是两个地方,装不装箱都是一个概念...
    ---------------------
    i分配的内存地址与o分配的内存地址根本就是两个地方,装不装箱都不是一个概念...注意...严重输入错误...
      

  7.   

    MSDN:
    相对于简单的赋值而言,装箱和取消装箱过程需要进行大量的计算。对值类型进行装箱时,必须分配并构造一个新对象。次之,取消装箱所需的强制转换也需要进行大量的计算。有关更多信息,请参见性能。--
    注意到这句 “必须分配并构造一个对象” 也是说 这不能象你解释的那样是引用指向这个值变量。
      

  8.   

    难道值类型每改变一次值,内存地址就改变一次么?MSDN:基于值类型的变量直接包含值。将一个值类型变量赋给另一个值类型变量时,将复制包含的值。这与引用类型变量的赋值不同,引用类型变量的赋值只复制对对象的引用,而不复制对象本身。
      

  9.   

    通过MSDN上的图解,是不是声明i后,i自己占个地方,然后当写下Object o = i后,程序复制了一个i放在另外的地方让O来引用,而后来i = 456  是修改原版的i,并没有修改盗版的i,所以打印出来i = 456,o= 123ps:大白话,大家别说我白....
      

  10.   

    你先别结贴,明天我再把书上是如何说的我输入来,好像MSDN上也有解使,但我找不到地方了。
    明天我再说,循便看看别人怎么说
      

  11.   

    参考:http://topic.csdn.net/u/20090908/23/9ad829f2-2f48-4f71-8b30-9dcec34cb5bb.html?54600http://topic.csdn.net/u/20081109/09/df55537b-db4b-4f38-a789-e94bd4020eeb.html
      

  12.   

    就是因为看你基础太浅,我一开始就说的很大白话了...“装箱以后,o和i没有任何关系了,i是i,o是o”...那些什么引用类型转换、值类型转换、内存地址的,你不分清楚只会越看越糊涂...你真要搞清楚,就要先搞清楚.NET内存的管理方式...这些基础概念就应该去看书,而不是在这儿听大家七嘴八舌的越说越乱...我先给你简单讲讲,你还是去找本入门书认真看看好...1. .NET将物理内存块分为两个数据存储区,栈(stack)和托管堆(managed heap),托管堆又划分为多个区域,其中与装拆箱密切相关是垃圾回收堆(GC heap)...2.栈是一小块特殊的物理内存块,它的性能非常高,但是大小很有限...在.NET中只有1M,所以只允许存放值类型实例、引用类型的引用和进程数据...3.托管堆是连续分配的自由存储区,访问速度较慢,所有引用类型实例的值都存在这里...上面只是简单的介绍,更详细的去看书...下面的看清楚了,你可以把栈和垃圾回收堆想象成两个不同的房间...int i = 123; 声明一个值类型对象并赋值,这个值类型实例i是被创建在栈上的...它的内存地址在生存周期结束之前始终不会变...object o = i; 声明一个引用类型对象o,这个o的引用是被创建在栈上的...但是,将值类型实例i的值赋值给o时,由于o的值是被创建在垃圾回收堆上的,所以会把在栈上的i复制一份拷贝到垃圾回收堆上...到这里,i和o就没有任何关系了...o的引用的内存地址在生存周期结束之前始终不会变,而o的值的内存地址则可能会变,即使你没改它GC清理内存时也可能会移动它的位置...i = 456; 这时你更改i的值只是在改栈上的数据,跟堆上那个“装箱”的o的值完全没有关系...它的内存地址不会变...其实装拆箱只是实现了“转换”的功能,看起来是“转换”实际并不是“转换”...所以说,要么你就简直的理解为i装箱以后就和o没有联系了,要么就要认真去学学内存管理的详细内容...只拿些模糊不清的所谓“内存地址”出来忽悠,只会越解释越乱...
      

  13.   

    我也不想多说了,因为我也是初学者,如果说不好我怕别人会骂我。《C#入门经典第三版》:
    值类型在内存的一个地方(堆栈)存储它们自己和他们内容。
    引用类型在内存的一个地方(堆)存储一个引用,而在另一个地方存储内容。
    值类型和引用类型的一个区别是,值类型总是包含一个值,而引用类型可以是NULL空,表示它们不包含值。但
    是可以使用可空类型MSDN: 
    C#2008 :ms-help://MS.MSDNQTR.v90.chs/dv_csref/html/8da9bbf4-bce9-4b08-b2e5-f64c11c56514.htm
    int i = 123;
    object o = i;  // Implicit boxing
    i = 456;       // Change the contents of i此示例使用装箱将整数变量 i 转换为对象 o。这样,存储在变量 i 中的值就从 123 更改为 456。该示例表明原始值类型和装箱的对象使用不同的内存位置,因此能够存储不同的值。值类型的变量存储数据,而引用类型的变量(/对象)存储对实际数据的引用。基于值类型的变量直接包含值。将一个值类型变量赋给另一个值类型变量时,将复制包含的值。这与引用类型变量的赋值不同,引用类型变量的赋值只复制对对象的引用,而不复制对象本身。
    -------------------------------------------------------------
    总之,在这里,object o 始终是指向 123的。参考:
    http://terrylee.cnblogs.com/archive/2005/12/26/304876.aspxhttp://topic.csdn.net/u/20090328/10/1b3005e6-6662-4a84-aac5-6ab03b013273.html
      

  14.   

    楼上想说明什么?
    按你给的地址
    MSDN:
    ----------------------------------------------------------------------
    C#  复制代码 
    int i = 123;
    object o = (object)i;  // boxing
     然后,可以对对象 o 取消装箱并将其赋值给整型变量 i:C#  复制代码 
    o = 123;
    i = (int)o;  // unboxing
     性能
    相对于简单的赋值而言,装箱和取消装箱过程需要进行大量的计算。对值类型进行装箱时,必须分配并构造一个新对象。次之,取消装箱所需的强制转换也需要进行大量的计算。有关更多信息,请参见性能。
    ----------------------------------------------------------------------
    后面的 都是你的描述和推论吧,
    ----------------------------------------------------------------------
      此示例使用装箱将整数变量 i 转换为对象 o。这样,存储在变量 i 中的值就从 123 更改为 456。该示例表明原始值类型和装箱的对象使用不同的内存位置,因此能够存储不同的值。 值类型的变量存储数据,而引用类型的变量(/对象)存储对实际数据的引用。 基于值类型的变量直接包含值。将一个值类型变量赋给另一个值类型变量时,将复制包含的值。这与引用类型变量的赋值不同,引用类型变量的赋值只复制对对象的引用,而不复制对象本身。总之,在这里,object o 始终是指向 123的。
    ----------------------------------------------------------------------
    在你的这段描述中,有些部分我觉得是对的,但是加色和最后的总之部分,我觉得不是有问题就是多余描述或推论。
    object o=i;时 这个是box操作,不是引用之间的赋值操作,本来也就没有两引用类型嘛,
    这里就是box操作 MSDN已经说得很清楚 了“对值类型进行装箱时,必须分配并构造一个对象”;理解不了这个"新"字的含意吗?
      

  15.   

    个人来看,当把i装箱给o时,实际是把i的一个副本传给了o,对i的改跟i的副本(即o)没有任何关系。并不是直接让o这个指针指向i所在内存单元。所以这一点楼主是错误的理解。好多书上都有的,自己找找看,也可以多写几个例子证实下。
      

  16.   

    值类型的赋值中所复制的是真实的数据,而引用类型的赋值中复制的只是真实数据的内存地址而已(可以对联系C语言中的"&",它读的一个地址,这个地址中的值定了,你什么时候读它,它都是没变的)如果理解的深些,就像 29楼说的如下:int i = 123; 声明一个值类型对象并赋值,这个值类型实例i是被创建在栈上的...它的内存地址在生存周期结束之前始终不会变... object o = i; 声明一个引用类型对象o,这个o的引用是被创建在栈上的...但是,将值类型实例i的值赋值给o时,由于o的值是被创建在垃圾回收堆上的,所以会把在栈上的i复制一份拷贝到垃圾回收堆上...到这里,i和o就没有任何关系了...o的引用的内存地址在生存周期结束之前始终不会变,而o的值的内存地址则可能会变,即使你没改它GC清理内存时也可能会移动它的位置... i = 456; 这时你更改i的值只是在改栈上的数据,跟堆上那个“装箱”的o的值完全没有关系...它的内存地址不会变... 
      

  17.   

    首先 楼主在C#认识中有一个误区.简单的说, 当int   i   =   123; 时 i指向了一个地址 这个地址保存了一个值123      object   o   =   i;  这里o指向了 i的地址 123      i   =   456;  这里 只是更改了i的指向 指向了新的值 456其实是很简单的问题. C#的操作机制就是这样的.理解了就好了.
      

  18.   

    你都看了MSDN了,也把这段引用过来了...为什么就没看到这句话呢...
    32楼根本是错误解释,还有41楼回帖不看帖的典型...栈和托管堆根本是两块不同的内存区域中,何来“object o 始终是指向 123”、“o指向了 i的地址 123”?引用类型的值怎么可能在栈上?第3点很清楚...引用类型实例的引用存放在栈上,引用类型实例的存放在托管堆上....这也是初学者容易混淆的地方...引用类型实例是分成两部分,分别存放在栈和托管堆上的,要注意引用类型实例的引用和值是两码事...
      

  19.   

    楼主看这 文章  一定 了解了!http://terrylee.cnblogs.com/archive/2005/12/26/304876.aspx
      

  20.   

    相信vrhero,虽然有星星的不一定是高手(我在水源也有一个星星 :-)),但vrhero是广大同志鉴定过的,牛人~
      

  21.   


    String str1 = "abc";
    String str2 = "abc";
    System.out.println(str1==str2); //true
    可以看出str1和str2是指向同一个对象的。String str1 =new String ("abc");
    String str2 =new String ("abc");
    System.out.println(str1==str2); // false
      

  22.   

    1、基本数据类型存放在内存的栈区,引用类型实际是常量指针,也存放在栈区,但是引用类型所引用的对象也是由基本数据构成的,这些基本数据存放在堆区。
    2、基本数据类型在超出作用域后就立即释放栈区内存,引用数据类型在超出作用域后该常量指针也会立即释放栈区内存,但是他所引用的对象所包含的数据不会立即释放,会在后面的某一个时刻由垃圾回收器检测到,然后收回。
    3、在泛型里面只能使用引用类型,不能使用基本类型。
    4、在==操作符上,基本类型当然是比较值是否相等,引用类型是比较这两个引用是否指向同一地址。
    5、基本数据类型只能表示数据类型,而引用类型还能够表示复杂的数据类型
    6、java虚拟机处理基本数据类型变量和引用类型变量的方式是不一样的:java虚拟机在处理基本数据类型变量时会为其分配数据类型实际占用的内存空间;而对于引用类型变量,它只是指向堆区的一个实例的指针。
    7、引用类型的变量是对象具有可调用的方法,而基本数据类型则没有方法可以调用;
    说的不是 基本数据类型与引用类型的区别吗 ?
    有更详细的吗?