精华内容
下载资源
问答
  • 这里不讲垃圾回收的机制 ...我们都知道变量占有内存,内存在底层分配上有。 值类型变量的内存通常是在中分配 引用类型变量的内存通常在中分配 注意这里说的是通常,因为变量又分为局部变量和全局变量。 当变
  • Person p =new Person(“张三”,20); 这样的,我可不可以这样理解new Person(“张三”,20)在堆内存中创建,分配...Person p 在栈内存中创建,然后把堆内存中的内存地址付给栈内存中的p变量 我这样理解有错误吗
  • [转]Java中创建对象的区别

    千次阅读 2021-03-10 01:42:56
    与C++不同,Java自动管理,程序员不能直接地设置。Java的是一个运行时数据区,类的对象从中分配空间。这些对象通过new、newarray、anewarray和multianewarray等指令建立,它们不需要程序代码来显式的.....

    转载自http://blog.csdn.net/hbhhww/article/details/8152838

    栈与堆都是Java用来在Ram中存放数据的地方。与C++不同,Java自动管理栈和堆,程序员不能直接地设置栈或堆。

    Java的堆是一个运行时数据区,类的对象从中分配空间。这些对象通过new、newarray、anewarray和multianewarray等指令建立,它们不需要程序代码来显式的释放。堆是由垃圾回收来负责的,堆的优势是可以动态地分配内存大小,生存期也不必事先告诉编译器,因为它是在运行时动态分配内存的,因此,用堆保存数据时会得到更大的灵活性。变量所需的存储空间只有在运行时创建了对象之后才能确定。Java的垃圾收集器会自动收走这些不再使用的数

    据。但缺点是,由于要在运行时动态分配内存,存取速度较慢。

    栈的优势是,存取速度比堆要快,仅次于寄存器,栈数据可以共享。但缺点是,存在栈中的数据大小与生存期必须是确定的,缺乏灵活性。栈中主要存放一些基本类型的变量(,int, short, long, byte, float, double, boolean, char)和引用对象,栈里存的却是堆的首地址名;就像引用变量。

    Java中分配堆内存是自动初始化的。Java中所有对象的存储空间都是在堆中分配的,但是这个对象的引用却是在堆栈中分配,也就是说在建立一个对象时从两个地方都分配内存,在堆中分配的内存实际建立这个对象,而在栈中分配的内存只是一个指向这个堆对象的指针(引用变量)而已。 在堆中分配的内存,由Java虚拟机的自动垃圾回收器来管理。

    在堆中产生了一个数组或对象后,还可以在栈中定义一个特殊的变量,让栈中这个变量的取值等于数组或对象在堆内存中的首地址,栈中的这个变量就成了数组或对象的引用变量。

    引用变量是普通的变量,定义时在栈中分配,引用变量在程序运行到其作用域之外后被释放。而数组和对象本身在堆中分配,即使程序运行到使用 new 产生数组或者对象的语句所在的代码块之外,数组和对象本身占据的内存不会被释放,数组和对象在没有引用变量指向它的时候,才变为垃圾,不能在被使用,但仍然占据内存空间不放,在随后的一个不确定的时间被垃圾回收器收走(释放掉)。

    例子:

    String s=new String("123");

    这个s就在栈里面,而他的"123"这个对象在堆里面。 s 指向"123";

    3.就对象本身而言,他的所有属性的值如果不是单例或者静态的,就是存储在堆里面的。一个类的所有对象的属性值都在堆里面并且占用不同的内存空间,而一个类的方法只在方法区里占一个地方

    栈有一个很重要的特殊性,就是存在栈中的数据可以共享。假设我们同时定义:

    int a = 3;

    int b = 3;

    编译器先处理int a = 3;首先它会在栈中创建一个变量为a的引用,然后查找栈中是否有3这个值,如果没找到,就将3存放进来,然后将a指向3。接着处理int b = 3;在创建完b的引用变量后,因为在栈中已经有3这个值,便将b直接指向3。这样,就出现了a与b同时均指向3的情况。

    这时,如果再令a=4;那么编译器会重新搜索栈中是否有4值,如果没有,则将4存放进来,并令a指向4;如果已经有了,则直接将a指向这个地址。因此a值的改变不会影响

    到b的值。

    a-------》3

    b-------》3 ,这个3是共享存在的,a,b指向同一个地址,然后存进4,4也是共享存在的。

    a,b先指向3个共享,然后a指向4,b仍然指向3.

    3和4是存放在栈中,a和b是引用对象

    要注意这种数据的共享与两个对象的引用同时指向一个对象的这种共享是不同的,因为这种情况a的修改并不会影响到b, 它是由编译器完成的,它有利于节省空间。而一

    个对象引用变量修改了这个对象的内部状态,会影响到另一个对象引用变量。

    String是一个特殊的包装类数据。可以用:

    String str = new String("abc");------------------开辟新的空间,创建新对象

    String str = "abc"; -----------------------------使用共享的字符串

    两种的形式来创建,第一种是用new()来新建对象的,它会在存放于堆中。每调用一次就会创建一个新的对象。

    而第二种是先在栈中创建一个对String类的对象引用变量str,然后查找栈中有没有存放"abc",如果没有,则将"abc"存放进栈,并令str指向”abc”,如果已经有”abc” 则直接令str指向“abc”,相当于指向“abc”的地址。

    比较类里面的数值是否相等时,用equals()方法;当测试两个包装类的引用是否指向同一个对象时,用,下面用例子说明上面的理论。

    String str1 = "abc";

    String str2 = "abc";

    System.out.println(str1str2); //true

    可以看出str1和str2是指向同一个对象的。

    String str1 =new String ("abc");

    String str2 =new String ("abc");

    System.out.println(str1==str2); // false

    用new的方式是生成不同的对象。每一次生成一个。

    因此用第二种方式创建多个”abc”字符串,第一种方式在内存中其实只存在一个对象而已. 这种写法有利与节省内存空间. 同时它可以在一定程度上提高程序的运行速度

    ,因为JVM会自动根据栈中数据的实际情况来决定是否有必要创建新对象。而对于String str = new String("abc");的代码,则一概在堆中创建新对象,而不管其字符串值是否相

    等,是否有必要创建新对象,从而加重了程序的负担。

    另一方面, 要注意: 我们在使用诸如String str = "abc";的格式定义类时,总是想当然地认为,创建了String类的对象str。担心陷阱!对象可能并没有被创建!而可能

    只是指向一个先前已经创建的对象。只有通过new()方法才能保证每次都创建一个新的对象。

    展开全文
  • 如果需要在上创建对象,要么使用new运算符,要么使用malloc系列函数。这点没有异议。 真正有异议的是下面的代码: Object obj; 此时,obj是在上分配的吗? 要回答这个问题,我们首先要理解这个语句是什么...

    https://blog.csdn.net/Solo_two/article/details/79780086

    如果需要在堆上创建对象,要么使用new运算符,要么使用malloc系列函数。这点没有异议。

    真正有异议的是下面的代码:

    Object obj;

    此时,obj是在栈上分配的吗?

    要回答这个问题,我们首先要理解这个语句是什么意思。这个语句就是代表着,在栈上创建对象吗?

    其实,这行语句的含义是,使对象obj具有“自动存储(automatic storage)”的性质。所谓“自动存储”,意思是这个对象的存储位置取决于其声明所在的上下文。

    如果这个语句出现在函数内部,那么它就在栈上创建对象。

    如果这个语句不是在函数内部,而是作为一个类的成员变量,则取决于这个类的对象是如何分配的。考虑下面的代码:

    class Class
    {
        Object obj;
    };
     
    Class *pClass = new Class;

      // 指针pClass所指向的对象在堆上分配空间。

      // 因为Object obj;语句的含义是“自动存储”,所以,pClass->obj也是在堆上创建的。

     

    Object *pObj;
    pObj = new Object;
    // Object *pObj;代表,指针pObj是自动存储
    // 仅此而已,没有任何其它含义。
    // 而之后一行语句则指出,这个指针所指向的对象是在堆上面分配的。

    如果这两行语句出现在一个函数内部,意味着当函数结束时,pObj会被销毁,但是它指向的对象不会。因此,为了继续使用这个对象,通常我们会在函数最后添加一个return语句,或者使用一个传出参数。否则的话,这个在堆上创建的对象就没有指针指向它,也就是说,这个对象造成了内存泄露。

    并不是说指针指向的对象都是在堆上创建的。下面的代码则使用指针指向一个在栈上创建的对象:

    Object obj;
    Object *pObj = &obj;

    至此,我们解释了函数内部的变量和成员变量。还有两类变量:全局变量和static变量。它们即不在堆上创建,也不在栈上创建。它们有自己的内存空间,是除堆和栈以外的数据区。也就是说,当Object obj即不在函数内部,又不是类的成员变量时,这个对象会在全局数据段创建,同理适用于static变量。对于指针Object *pObj;,如果这个语句出现在函数内部或类的成员变量,正如我们前面所说的,这个指针是自动存储的。但是,如果这个语句是在类的外部,它就是在全局数据段创建的。虽然它指向的对象可能在堆上创建,也可能在栈上创建。

    堆和栈的区别在于两点:

    1. 生命周期
    2. 性能

    第一点才是我们需要着重考虑的。由于栈的特性,如果你需要一个具有比其所在的上下文更长的生命周期的变量,只能在堆上创建它。所以,我们的推荐是:只要能在栈上创建对象,就在栈上创建;否则的话,如果你不得不需要更长的生命周期,只能选择堆上创建。这是由于在栈上的对象不需要我们手动管理内存。有经验的开发人员都会对内存管理感到头疼,我们就是要避免这种情况的发生。总的来说,我们更多推荐选择在栈上创建对象。

    但是,有些情况,即便你在栈上创建了对象,它还是会占用堆的空间。考虑如下代码:

    void func
    {
        std::vector v;
    }

    对象v是在栈上创建的。但是,STL 的vector类其实是在堆上面存储数据的(这点可以查看源代码)。因此,只有对象v本身是在栈上的,它所管理的数据(这些数据大多数时候都会远大于其本身的大小)还是保存在堆上。

    关于第二点性能,有影响,不过一般可以忽略不计。确切的说,一般情况下你不需要考虑性能问题,除非它真的是一个问题。

    首先,在堆上创建对象需要追踪内存的可用区域。这个算法是由操作系统提供,通常不会是常量时间的。当内存出现大量碎片,或者几乎用到 100% 内存时,这个过程会变得更久。与此相比,栈分配是常量时间的。其次,栈的大小是固定的,并且远小于堆的大小。所以,如果你需要分配很大的对象,或者很多很多小对象,一般而言,堆是更好的选择。如果你分配的对象大小超出栈的大小,通常会抛出一个异常。尽管很罕见,但是有时候也的确会发生。有关性能方面的问题,更多出现在嵌入式开发中:频繁地分配、释放内存可能造成碎片问题。

    现代操作系统中,堆和栈都可以映射到虚拟内存中。在 32 位 Linux,我们可以把一个 2G 的数据放入堆中,而在 Mac OS 中,栈可能会限制为 65M。

    总的来说,关于究竟在堆上,还是在栈上创建对象,首要考虑你所需要的生命周期。当性能真正成为瓶颈的时候,才去考虑性能的问题。堆和栈是提供给开发者的两个不同的工具,不存在一个放之四海而皆准的规则告诉你,一个对象必须放在堆中还是在栈中。选择权在开发者手中,决定权在开发者的经验中。

     

    转载于:https://www.cnblogs.com/qxxnxxFight/p/11137309.html

    展开全文
  • 一文详解堆栈(二)——内存内存栈

    万次阅读 多人点赞 2019-10-15 19:06:15
    前言:我们经常听见一个概念,(heap)和(stack),其实在数据结构中也有同样的这两个概念,但是这和内存的堆栈是不一样的东西哦,本文也会说明他们之间的区别的,另外,本文的只是是以C/C++为背景来说明,不同...

    前言:我们经常听见一个概念,堆(heap)和栈(stack),其实在数据结构中也有同样的这两个概念,但是这和内存的堆栈是不一样的东西哦,本文也会说明他们之间的区别的,另外,本文的只是是以C/C++为背景来说明,不同的语言在内存管理上面会有区别。本文是第二篇,介绍内存中的堆与栈。
     

    一、C++中的内存概述

    1.1 内存的分类标准——五分类

    在C++中,内存分成5个区,他们分别是堆,栈,自由存储区,全局/静态存续区,常量存续区
    (1)栈:内存由编译器在需要时自动分配和释放。通常用来存储局部变量函数参数,函数调用后返回的地址。(为运行函数而分配的局部变量、函数参数、函数调用后返回地址等存放在栈区)。栈运算分配内置于处理器的指令集中,效率很高,但是分配的内存容量有限。
    (2)堆:内存使用new进行分配,使用delete或delete[]释放。如果未能对内存进行正确的释放,会造成内存泄漏。但在程序结束时,会由操作系统自动回收。
    (3)自由存储区:使用malloc进行分配,使用free进行回收。
    (4)全局/静态存储区:全局变量静态变量被分配到同一块内存中,C语言中区分初始化和未初始化的,C++中不再区分了。(全局变量、静态数据 存放在全局数据区)
    (5)常量存储区:存储常量,不允许被修改。
     

    还有一些资料是将内存分为三类,如下。

    1.2 内存的分类标准——三分类
      这里,在一些资料中是这样定义C++内存分配的,可编程内存在基本上分为这样的几大部分:静态区、堆区、栈区。他们的功能不同,对他们使用方式也就不同。
    (1)静态(全局)存储区——static:内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。它主要存放静态数据、全局数据和常量。也是程序结束后,由操作系统释放。
    (2)栈区——stack:在执行函数时,函数参数,局部变量(包括const局部变量),函数调用后返回的地址都在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。
    (3)堆区——heap:亦称动态内存分配。程序在运行的时候用malloc或new申请任意大小的内存,程序员自己负责在适当的时候用free或 delete释放内存。动态内存的生存期可以由我们决定,如果我们不释放内存,程序将在最后才释放掉动态内存。 但是,良好的编程习惯是:如果某动态内存不再使用,需要将其释放掉,否则,我们认为发生了内存泄漏现象。

    1.3 内存的分类标准——另一种五分类

    (1)栈又叫堆栈,非静态局部变量/函数参数/返回值等等 ,还有每次调用函数时保存的信息。每当调用一个函数时,返回到的地址和关于调用者环境的某些信息的地址,比如一些机器寄存器,就会被保存在栈中。然后,新调用的函数在栈上分配空间,用于自动和临时变量。

    2.内存映射段是高效的I/O映射方式,用于装载一个共享的动态内存库。用户可使用系统接口创建共享共享内存,做进程间通信。

     3.堆用于程序运行时动态内存分配,堆是可以上增长的。堆区域从BSS段的末尾开始,并从那里逐渐增加到更大的地址。堆是由程序员自己分配的。堆区域由所有共享库和进程中动态加载的模块共享。

    4.数据段分为初始化数据段和未初始化数据段。初始化的数据段,通常称为数据段,是程序的虚拟地址空间的一部分,它包含有程序员初始化的全局变量和静态变量,可以进一步划分为只读区域和读写区域。未初始化的数据段,通常称为bss段,这个段的数据在程序开始之前有内核初始化为0,包含所有初始化为0和没有显示初始化的全局变量和静态变量。

    5.代码段也叫文本段,是对象文件或内存中程序的一部分,其中包含可执行代码和只读常量。文本段在堆栈的下面,是防止堆栈溢出覆盖它。,通常代码段是共享的,对于经常执行的程序,只有一个副本需要存储在内存中,代码段是只读的,以防止程序以外修改指令。
     

    1.4 内存的分类标准——四分类

    简单的介绍一下四个区域:

    (1)代码区--------主要存储程序代码指令,define定义的常量。

    (2)全局数据区------主要存储全局变量(常量),静态变量(常量),常量字符串。

    (3)栈区--------主要存储局部变量,栈区上的内容只在函数范围内存在,当函数运行结束,这些内容也会自动被销毁。其特点是效率高,但内存大小有限。

    (4)堆区--------由malloc,calloc分配的内存区域,其生命周期由free决定。堆的内存大小是由程序员分配的,理论上可以占据系统中的所有内存。
    四分类如下所示:

    个人偏好,四分类更好理解一些。注意这里的一些什么 .bss  .data这些代表什么含义。

    总结:

    • Stack memory内存,自动分配和释放,内存空间有限;
    • Heap Memory内存,手动分配和释放,空间是很大,几乎没有空间限制。

     

    1.5 函数调用后返回地址——保存在栈内存上

    函数调用时通过一个指向函数的指针指向函数,函数返回时将回归到调用处,那个地方就是函数调用结束后返回地址

    另外返回地址保存在栈上,最先调用的函数最早入栈,最后出栈,而最后调用的函数最后入栈,最先出栈。
     

    二、关于内存栈(memory stack)

    2.1 栈溢出

    “栈”由程序自动向操作系统申请分配以及回收,速度快,使用方便,但程序员无法控制。但是栈的空间很小,只要栈的剩余空间大于所申请空间,系统将为程序提供内存,若需要分配的空间大于栈内存,则分配失败,则提示栈溢出错误。

    #include <iostream>
    int main()
    {
        int i = 10;         //变量i储存在栈区中
        const int i2 = 20;  //const局部变量也存储在stack
        int i3 = 30;
        std::cout << &i << " " << &i2 << " " << &i3 << std::endl;
        return 0;
    }
    /*运行结果为:
     0x28fedc  0x28fed8 0x28fed4   16进制地址,递减的
    */

    注意:const局部变量也储存在栈区内,栈区向地址减小的方向增长。


    2.2 栈的特性

    (1)申请大小的限制
           在Windows下,栈是向低地址扩展的数据结构,是一块连续的内存的区域。这句话的意思是栈顶的地址和栈的最大容量是系统预先规定好的,在 Windows下,栈的大小是2M(也有的说是1M,总之是一个编译时就确定的常数),如果申请的空间超过栈的剩余空间时,将提示overflow。因此,能从栈获得的空间较小。

    (2)栈的申请效率很高
    栈由系统自动分配,速度较快。但程序员是无法控制的,结束后由操作系统进行释放。

    (3)栈使用的过程
           栈在函数调用时,

    • 第一个进栈的是主函数中后的下一条指令(函数调用语句的下一条可执行语句)的地址,
    • 然后是函数的各个参数,在大多数的C编译器中,参数是由右往左入栈的,
    • 然后是函数中的局部变量。注意静态变量是不入栈的。

    当本次函数调用结束后,局部变量先出栈,然后是参数,最后栈顶指针指向最开始存的地址,也就是主函数中的下一条指令,程序由该点继续运行。
     

    三、关于内存堆(memory heap)

    3.1 堆溢出

           堆是向高地址扩展的数据结构,是不连续的内存区域,这是由于系统使用链表存储空闲内存地址的,自然是不连续的。而链表的遍历方式是由低地址向高地址,堆的大小受限于计算机系统中有效的内存,由此可见,堆获得的空间比较灵活,也比较大。
           程序员向操作系统申请一块内存,当系统收到程序的申请时,会遍历一个记录空闲内存地址的链表,寻找第一个空间大于所申请空间的堆结点,然后将该结点从空闲结点链表中删除,并将该结点的空间分配给程序。分配的速度较慢,地址不连续,容易碎片化。此外,由程序员申请,同时也必须由程序员负责销毁,否则导致内存泄露
     

    3.2 堆的特性
           操作系统有一个记录空闲内存地址的链表,当系统收到程序的申请时,会遍历该链表,寻找第一个空间大于所申请空间的堆结点,然后将该结点从空闲结点链表中删除,并将该结点的空间分配给程序,另外,对于大多数系统,会在这块内存空间中的首地址处记录本次分配的大小,这样,代码中的delete语句才能正确的释放本内存空间。另外,由于找到的堆结点的大小不一定正好等于申请的大小,系统会自动的将多余的那部分重新放入空闲链表中

    (1)申请大小的限制
          堆是向高地址扩展的数据结构,是不连续的内存区域。这是由于系统是用链表来存储的空闲内存地址的,自然是不连续的,而链表的遍历方向是由低地址向高地址。堆的大小受限于计算机系统中有效的物理内存。由此可见,堆获得的空间比较灵活,也比较大。
    (2)堆的使用效率
    堆是由new分配的内存,一般速度比较慢,而且容易产生内存碎片,不过用起来最方便。

    (3)堆使用的过程
    堆:一般是在堆的头部用一个字节存放堆的大小。堆中的具体内容有程序员安排。
     

    总结:

    栈内存:由高地址向低地址,连续,快速,空间小;

    栈内存:由低地址向高地址,不连续,缓慢,空间大。

    可以列举成下面的表格:

     申请方式内存大小使用效率存储内容
    栈(stack)自动申请释放高效 
    堆(heap)手动申请释放缓慢 

     

    四、为什么C,C++在传递数组的时候传递的是地址或者是引用呢?

    从上面的分析可以知道,由于函数的参数存储在栈内存中,所以如果一个数组比较大,我传递一个很大的数组,如果复制的是数组的值到形参上面,必然会导致栈内存不够用,即“栈溢出”,所以只传递一个地址值,而不传递实际的值就可以避免这一问题,其实向java,C#这些语言也有着相同的底层原理,后面继续说明。

    总结:

    我们在C语言里面函数的参数传递经常分为,值传递/指针传递

    在C#,Java,C++里面函数的参数传递我们经常分为,值传递/引用传递

    其实从内存的“栈内存”角度来说,所有的函数参数传递都只有一种形式,那就是值传递。

    因为如果参数是值,则会拷贝栈里面的值到函数的形参里面去,这当然是值传递了,

    如果参数是地址或者是引用,其实同样是会拷贝存在在栈区域里面的地址或者是引用传递到函数形参,只不过这个地址或者是引用不是真正的数据,拷贝的那个相同的地址或者谁引用会指向同一段数据,所以我们称之为传递引用或者是地址。

    总而言之:传递地址或者是引用只是表面,本质都是“值传递”。

    个人理解,如果大神有更好地理解,希望可以分享告知,谢谢。想要彻底弄懂这些概念,还是结合几篇文章一起看更好理解。

     

    五、C#的内存管理

    详细可以参考我的另外一篇文章:

    一文读懂C#的 堆、栈、值类型、引用类型

    C# (CLR) 中内存分配解析

     

     

     

    展开全文
  • Java数组 在进入讲解主题“-栈内存堆内存的区别”之前,先来讲解一下数组,所谓数组,就是若干个相同数据...在方法中定义的一些基本类型的变量和对象的引用变量都在方法的栈内存中分配,当在一段代码块中定义一个变...

    Java数组
    在进入讲解主题“-栈内存与堆内存的区别”之前,先来讲解一下数组,所谓数组,就是若干个相同数据类型的元素按一定顺序排列的集合。
    一维数组的定义:
    数据类型[ ] 数组名;
    数组名 = new 数据类型[个数];

    针对于Java数组,Java语言把内存分为两种:-栈内存和堆内存。
    栈内存:
    在方法中定义的一些基本类型的变量和对象的引用变量都在方法的栈内存中分配,当在一段代码块中定义一个变量时,Java就在栈内存中为这个变量分配内存空间,当超出变量的作用域后,Java会自动释放掉为该变量所分配的内存空间。
    堆内存:
    堆内存用来存放 new 运算符创建的对象和数组,在堆中分配的内存,由Java虚拟机的自动垃级回收器来管理。在堆中创建了一个数组或对象后,同时还在栈中定义一个特殊的变量,让栈中的这个变量的取值等于数组或对象在堆内存中的首地址,栈中的这个变量就成了数组或对象的引用变量,引用变量实际上保存的是数组或对象在堆内存中的首地址(也称为对象的句柄),以后就可以在程序中使用栈的引用变量访问堆中的数组或对象。引用变量就相当于是为数组或对象起的一个名称。引用变量是普通的变量,定义时在找中分配,引用变量在程序运行到其作用域之外后被释放。而数组或对象本身在堆内存中分配,即使程序运行到使用new运算符创建数组或对象的语句所在的代码块之外,数组或对象本身所占据的内存也不会释放,数组或对象在没有引用变量指向它时,会变为垃圾,不能再被使用,但仍然占据内存空间不放,在随后一个不确定的时间被垃圾回收器收走(释放掉),这也是Java比较占内存的原因。
    小结:
    1 栈:为编译器自动分配和释放,如函数参数、局部变量、临时变量等等
    2 堆:为成员分配和释放,由程序员自己申请、自己释放。否则发生内存泄露。典型为使用 new 申请的堆内容。
    为了方便理解,举个例子:
    如: int [ ] x; //定义了一个数组x,这条语句执行完成后的内存状态如图1
    x = new int [10]; //数组初始化,这条语句执行完成后的内存状态如图2
    图1.只声明了数组,而没有对其分配内存空间图1.只声明了数组,而没有对其分配内存空间
    图2.声明数组并分配相应的内存空间,引用变量指向数据对象图2.声明数组并分配相应的内存空间,引用变量指向数据对象

    执行第2条语句"x=new int [10];“后,在堆内存中创建了一个数组对象,为这个数组对象分配了10个整数单元,并将数组对象赋给了数组引用变量x,引用变量就相当于C语言中的指针变量,而数组对象就是指针变量指向的那个内存块。所以说在Java内部还是有指针的,只是把指针的概念对用户隐藏起来了,而用户所使用的是引用变量。
    用户也可以改变x的值,让它指向另外一个数组对象,或者不指向任何数组对象。要想让x不指向任何数组对象,只需要将常量 null 赋给x即可。如x=null;,这条语句执行完后的内存状态如图3所示。
    执行完"x=null;”,语句后,原来通过new int [10]产生的数组对象不再被任何引用变量所引用,变成了“孤儿”,也就成了垃圾,直到垃圾回收器来将它释放掉.
    图3.引用变量与引用对象断开
    图3.引用变量与引用对象断开

    栈内存与堆内存的区别讲述完毕,迷路的你,是否看到了些许光芒。
    为每一个不死心的明天而拼命的今天,都是2019年11月19日21点24分。
    刚刚结束今天的马原期中,Java加油啊!

    展开全文
  • new创建对象对象保存在堆还是栈? –>堆内存是用来存放由new创建的对象和数组,即动态申请的内存都存放在堆内存 –>栈内存是用来存放在函数中定义的一些基本类型的变量和对象的引用变量 例子: 局部变量,...
  • 吃人的那些 Java 名词:对象、引用、

    万次阅读 多人点赞 2019-09-05 15:57:09
    作为一个有着 8 年 Java 编程经验的 IT 老兵,说起来很惭愧,我被 Java 当中的四五个名词一直困扰着:**对象、引用、、堆栈**(可同堆栈,因此是四个名词,也是五个名词)。每次我看到这几个名词,都隐隐...
  • 简单翻译下:Heap space 空间: 所有存活的对象在此分配.Stack space 空间: 方法调用时保存变量对象的引用或变量实例.Perm space : 保存已加载的类的信息.如:Student std = new Student();执行后内存情况如下:Heap...
  • 前几天去BAT某公司笔试。有一题C#引用类型存在哪里?以前也学过一点,知道C#...这个变量指向的对象堆里,我就不知道这个引用类型到底是指栈里的变量,还是堆里对象。 查了很多资料没有看明白,求专业人士指点。
  • 栈内存:当对象** 所在的函数体**执行完毕时,栈内存里的数据就会被清理。如:Student std;(是栈内存) 堆内存:会一直存在,执行delete是会清楚。如果是指针要记得将指针置nullptr。如:Student str = new Student()...
  • java中栈内存堆内存(JVM内存模型)Java中堆内存栈内存详解1 和 Java中堆内存栈内存详解2 都粗略讲解了栈内存堆内存的区别,以及代码中哪些变量存储在中、哪些存储在中。内存中的到底是什么 详细...
  • 成员变量在堆内存里,局部变量在栈内存里。(基础类型) 我有疑惑: 既然成员变量存在于对象中,对象存在中,所以成员变量存在于中。那么按照这样的推理,局部变量存在于方法中,而方法存在于对象中,对象存在...
  • 然后涉及到多线程的问题时,又存在一个主存和线程运行内存的概念,我理解主存就是说的,线程运行内存就是分配给线程的;那如果在线程的run方法new一个对象,它是放哪呢? 如果放堆里那不是成了共享变量了?...
  • C# 堆内存 vs 栈内存 (1)

    千次阅读 2018-05-06 22:50:52
    概述 在.Net当中,有Clr帮我们进行内存管理和垃圾回收,但这并不意味着我们不需要关心这些机制。...当程序运行时,.Net会在两个地方存储程序信息,堆内存栈内存,它们只是对内存的逻辑分段,在程序...
  • Java引用对象栈内存中的变化

    千次阅读 2018-09-04 21:18:20
    1、对象主要存放在堆内存中;方法和属性主要存放在栈内存中。 2、是运行时单位,用来解决程序运行时的问题,是存储单位,解决数据存储的问题。 3、伴随着JVM的启动而创建。 下面是一段程序执行过程,对象和...
  • 区:  1.存储的全部是对象,每个对象都包含一个与之对应的...1.每个线程包含一个区,中只保存基础数据类型的对象和自定义对象的引用(不是对象),对象都存放在区中 2.每个中的数据(原始类型和对象引用...
  • 栈内存堆内存有什么区别?

    千次阅读 2019-03-22 18:17:00
    栈内存堆内存有什么区别? 栈内存堆内存是什么?有什么用? 栈内存堆内存是什么? 栈内存堆内存都是存储数据的地方。 为什么会分栈内存堆内存?? 因为栈内存中存储的值的大小是固定的,...
  • vector数据存在栈还是堆

    万次阅读 2018-05-16 13:03:02
    推测:vector这个对象存在栈中,然后中有指向vector所存数据的地址,数据保存在中。
  • 关于究竟是在还是上创建对象,可能很多初学者感到迷惑。我想可以把这部分内容拿出来详细介绍一下。现在,假设你已经清楚什么是,什么是。如果需要在上创建对象,要么使用new运算符,要么使用malloc...
  • 堆内存完全由JVM负责分配和释放,如果程序没有缺陷代码导致内存泄露,那么就不会遇到java.lang.OutOfMemoryError这个错误。 使用内存,就是为了能直接分配和释放内存,提高效率。JDK5.0之后,代码中能直接操作...
  • 栈对象堆对象和静态对象比较

    千次阅读 2018-08-09 14:01:49
    而且栈对象的创建速度一般较堆对象快,因为分配堆对象时,会调用operator new操作,operator new会采用某种内存空间搜索算法,而该搜索过程可能是很费时间的,产生栈对象则没有这么麻烦,它仅仅需要移动栈顶指针就...
  • 栈内存的一个特点是数据共享,堆内存没有数据共享的特点。
  • Java内存分配详解(堆内存栈内存、常量池)

    万次阅读 多人点赞 2017-10-23 21:04:47
    Java程序是运行在JVM(Java虚拟机)上的,因此Java...2. :存放基本类型的数据和对象的引用,但对象本身不存放在中,而是存放在中。 3. :存放new出来的对象,注意创建出来的对象只包含各自的成员变量,不包括成
  • js中的栈内存堆内存

    千次阅读 2018-12-11 17:16:37
    1.简介 ...:动态分配的内存,物理地址不连续,大小不定也不会自动释放,存放引用类型, 指那些可能由多个值构成的对象,保存在堆内存中,包含引用类型的变量,实际上保存的不是变量本...
  • Java 内存管理()及 垃圾回收算法一.Jvm虚拟机内存简介1.1 Java运行时内存区1.2 线程私有的如下:1.3 线程共享的如下:二.Java 2.1 堆栈的概念和特点2.2 的异同2.3 举个例子另注:三.垃圾回收...
  • java堆内存栈内存的区别

    千次阅读 2015-11-03 14:05:48
    一段时间之前,我写了两篇文章文章分别是Java的垃圾回收和Java的值传递,从那...Java堆内存堆存在Java运行时被使用来为对象和JRE类分配内存。不论什么时候我们创建了对象,它将一直会在堆内存上创建。垃圾回收运行...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 181,808
精华内容 72,723
关键字:

对象存在内存的栈里还是堆里