精华内容
下载资源
问答
  • 对象在栈区还是堆区
    万次阅读
    2018-05-16 13:03:02
    推测:vector这个对象存在栈中,然后栈中有指向vector所存数据的地址,数据保存在堆中。
    更多相关内容
  • 通常情况下,对象创建在堆还是在栈上,创建多少个,这都是没有限制的。但是有时会遇到一些特殊需求。 1.禁止创建栈对象 禁止创建栈对象,意味着只能在堆上创建对象。创建栈对象时会移动栈顶指针以“挪出”适当大小...
  • 如果需要在堆上创建对象,要么使用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

    展开全文
  • C++ 类中的数组成员在栈还是堆区

    千次阅读 2020-04-07 15:49:38
    C++ 类中的数组成员在栈还是堆区 如下 ``` class A{ public: A(){ a=new int[10];} int * a; int b[10]; } int main() { A* pa=new A[100]; } ``` pa->a 与pa->b 在堆区还是栈区 编译器分配还是.....

    C++ 类中的数组成员在栈区还是堆区

    如下

    ```
    class A{
        public:
            A(){
            a=new int[10];}
            int * a;
            int b[10];
    }

    int main()
    {
        A* pa=new A[100];
    }
    ```
    pa->a 与pa->b 在堆区还是栈区
    编译器分配还是运行期分配

    展开全文
  • 本文为joshua317原创文章,转载请注明:转载自joshua317...一般Java内存分配时会涉及到这几个区域:区(stack)、堆区(heap)、方法区(Method Area)、常量池。我们先对下面几个概念进行深刻了解后,再进行画图.

    本文为joshua317原创文章,转载请注明:转载自joshua317博客 Java 类和对象在内存中的表现形式,栈、堆、方法区、常量池 - joshua317的博客

    Java内存分配与管理是Java的核心技术之一,不管学习任何一门语言,我们要知其然,知其所以然,本文主要分析下Java中类和对象在内存中的表现形式,方便我们对其有更深了解。一般Java在内存分配时会涉及到这几个区域:栈区(stack)、堆区(heap)、方法区(Method Area)、常量池。我们先对下面几个概念进行深刻了解后,再进行画图分析类和对象在内存中的变化及表现形式。

    栈:存放基本类型的数据和对象的引用变量的数据,但对象本身不存放在栈中,而是存放在堆中(new 出来的对象)

    堆:存放用new产生的对象数据,每个对象包含了一个与之对应的 class 类的信息。

    方法区(又称为静态区):存放对象中用static定义的静态成员

    常量池:通常用来存放常量数据、静态变量、类的加载信息等

    一、栈区

    在函数(方法)中定义的一些基本类型的变量或者对象的引用变量都在栈内存中分配。

    当在一段代码块定义一个变量时,Java就在栈中为这个变量分配内存空间,当该变量退出该作用域后,Java会自动释放掉为该变量所分配的内存空间,该内存空间可以立即被另作他用。栈中的数据大小和生命周期是可以确定的,当没有引用指向数据时,这个数据就会消失。

    每个方法(Method)执行时,都会创建一个方法栈区,用于存储局部变量表、操作数栈、动态链接、方法出口信息等

    栈中所存储的变量和引用都是局部的(即:定义在方法体中的变量或者引用),局部变量和引用都在栈中(包括final的局部变量)

    八种基本数据类型(byte、short、int、long、float、double、char、boolean)的局部变量(定义在方法体中的基本数据类型的变量)在栈中存储的是它们对应的值

    每个线程包含一个栈区,栈中只保存基本数据类型的变量和引用数据类型的变量,每个栈中的数据(基本数据类型和对象的引用)都是私有的,其它栈是无法进行访问的。栈分为3个部分:基本类型变量区、执行环境上下文、操作指令区(存放操作指令)。

    栈中还存储局部的对象的引用(定义在方法体中的引用类型的变量)对象的引用并不是对象本身,而是对象在堆中的地址,换句话说,局部的对象的引用所指对象在堆中的地址在存储在了栈中。当然,如果对象的引用没有指向具体的对象,对象的引用则是null

    栈的优势是,存取速度比堆要快,仅次于寄存器,栈数据可以共享。但缺点是,存在栈中的数据大小与生存期必须是确定的,缺乏灵活性。

    栈有一个很重要的特殊性,就是存在栈中的数据可以共享。

    二、堆区

    堆内存用来存放由new创建的对象和数组。在堆中分配的内存,由Java虚拟机的自动垃圾回收器来管理。

    堆内存是被所有线程共享的一块内存区域,在虚拟机启动时创建。Java堆(Java Heap)唯一目的就是存放对象实例。所有的对象实例及数组都要在**Java堆(Java Heap)**上分配内存空间。

    在堆中产生了一个数组或对象后,在栈中定义一个特殊的变量,让栈中这个变量的取值等于数组或对象在堆内存中的首地址,栈中的这个变量就成了数组或对象的引用变量。引用变量就相当于是为数组或对象起的一个名称,以后就可以在程序中使用栈中的引用变量来访问堆中的数组或对象。引用变量就相当于是为数组或者对象起的一个名称。

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

    实际上,栈中的变量指向堆内存中的变量,这就是Java中的指针!

    Java的堆是一个运行时数据区,类的对象从中分配空间。对象一般通过new 来创建,例如new Date(),它们不需要程序代码来显式的释放。堆是由垃圾回收来负责的,堆的优势是可以动态地分配内存大小,生存期也不必事先告诉编译器,因为它是在运行时动态分配内存的,Java的垃圾收集器会自动收走这些不再使用的数据。但缺点是,由于要在运行时动态分配内存,存取速度较慢。

    三、方法区

    方法区跟堆一样,又被称为静态区,通常存放常量数据。它存储已被Java虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等,它跟堆一样,被所有的线程共享。

    3.1 存储的类信息

    对每个加载的类型(类class、接口interface、枚举enum、注解annotation),JVM必须在方法区中存储以下类型信息:

    • 这个类型的完整有效名称(全名=包名.类名)

    • 这个类型直接父类的完整有效名称( java.lang.Object除外,其他类型若没有声明父类,默认父类是Object)

    • 这个类型的修饰符(public、abstract、final的某个子集)

    • 这个类型直接接口的一个有序列表

    除此之外还方法区(Method Area)存储类信息还有

    • 类型的常量池( constant pool)

    • 域(Field)信息

    • 方法(Method)信息

    • 除了常量外的所有静态(static)变量

    3.2 存储的常量

    static final修饰的成员变量都存储于 方法区(Method Area)中

    3.3 存储的静态变量

    • 静态变量又称为类变量,类中被static修饰的成员变量都是静态变量(类变量)

    • 静态变量之所以又称为类变量,是因为静态变量和类关联在一起,随着类的加载而存在于方法区(而不是堆中)

    • 八种基本数据类型(byte、short、int、long、float、double、char、boolean)的静态变量会在方法区开辟空间,并将对应的值存储在方法方法区,对于引用类型的静态变量如果未用new关键字为引用类型的静态变量分配对象(如:static Object obj;),那么对象的引用obj会存储在方法区中,并为其指定默认值null;若对于引用类型的静态变量如果用new关键字为引用类型的静态变量分配对象(如:static Cat cat = new Cat();),那么对象的引用cat会存储在方法区中,并且该对象在堆中的地址也会存储在方法区中(注意此时静态变量只存储了对象的堆地址,而对象本身仍在堆内存中);当然这个过程还涉及到静态变量初始化问题。

    3.4 存储的方法(Method)

    程序运行时会加载类编译生成的字节码,这个过程中静态变量(类变量)和静态方法及普通方法对应的字节码加载到方法区。

    方法区中没有实例变量,这是因为,类加载先于对应类对象的产生,而实例变量是和对象关联在一起的,没有对象就不存在实例变量,类加载时没有对象,所以方法区中没有实例变量。

    静态变量(类变量)和静态方法及普通方法在方法区(Method Area)存储方式是有区别的

    四、常量池

    常量池指的是在编译期被确定,并被保存在已编译的.class文件中的一些数据。

    除了包含代码中所定义的各种基本类型(如int、long等等)和对象型(如String及数组)的常量值(final)还包含一些以文本形式出现的符号引用,比如:类和接口的全限定名;字段的名称和描述符;方法和名称和描述符。

    虚拟机必须为每个被装载的类型维护一个常量池。常量池就是该类型所用到常量的一个有序集和,包括直接常量(string,integer和floating point常量)和对其他类型,字段和方法的符号引用。对于String常量,它的值是在常量池中的。而JVM中的常量池在内存当中是以表的形式存在的,对于String类型,有一张固定长度的CONSTANT_String_info表用来存储文字字符串值,注意:该表只存储文字字符串值,不存储符号引用。说到这里,对常量池中的字符串值的存储位置应该有一个比较明了的理解了。在程序执行的时候,常量池会储存在方法区(Method Area),而不是堆中。

    五、画图分析类实例化及操作时在内存中的变化及表现形式

    package com.joshua317;
    
    public class Main {
    
        public static void main(String[] args) {
            //实例化一个Cat对象
            Cat cat = new Cat();
            //给成员变量赋值
            cat.name = "招财";
            cat.age = 2;
            cat.weight = 2.02;
            //打印
            System.out.println("小猫的名字:"+cat.name + " 小猫的年龄:"+cat.age);
            //调用成员方法
            cat.say();
        }
    }
    
    class Cat {
        /**
         * 成员变量 name
         */
        String name;
        /**
         * 成员变量 age
         */
        int age;
        /**
         * 成员变量 weight
         */
        double weight;
    
        public void say()
        {
            System.out.println("喵喵~~");
        }
    }

    Java

    Copy

    上面这段代码首先有个主程序的类Main,这个我们不过多说明。我们主要分析main函数体里面的这段代码。

    我们需要知道在Cat类中,定义了三个成员属性:name、age、weight;定义了一个成员方法:say();

    //实例化一个Cat对象
    Cat cat = new Cat();
    //给成员变量赋值
    cat.name = "招财";
    cat.age = 2;
    cat.weight = 2.02;
    //打印
    System.out.println("小猫的名字:"+cat.name + " 小猫的年龄:"+cat.age);
    //调用成员方法
    cat.say();
    

    在main() 函数里实例化对象 cat, 内存中在堆区内会给实例化对象 cat 分配一个内存地址,然后我们给对象 cat进行了赋值并且打印了一些信息,最后调用了成员方法 say() ,程序执行完毕。

    1.在程序的执行过程中,首先Main类中的成员属性和成员方法会加载到方法区

    2.程序执行类Main的main() 方法时,main()函数方法体会进入栈区,这一过程叫做进栈(压栈)。

    3.程序执行到 Cat cat = new Cat(); 时,首先会把Cat类的成员属性和成员方法加载到方法区,此时方法的内存空间地址为1x000000,同时在在堆内存开辟一块内存空间74a14482,用于存放 Cat 实例对象,并给成员属性及成员方法分配对应的地址空间,比如下图的0x000001~0x000004即为对象分配的堆内存地址,但此时成员属性都是默认值,比如int类型默认值为0,String类型默认值为null,成员方法地址值为方法区对应成员方法体的内存地址值;然后在栈内存中会给变量cat分配一个栈地址34b23231,用来存放Cat实例对象的引用地址的值74a14482

    4.接下来对 cat 对象进行赋值

    //给成员变量赋值
    cat.name = "招财";
    cat.age = 2;
    cat.weight = 2.02;
    

    先在栈区找到引用变量cat,然后根据地址值找到 new Cat() 对象的内存地址,并对里面的属性进行赋值操作。由于成员属性name的类型为String,为引用数据类型,所以此时会在常量池开辟一块地址空间2x00000000,存放招财这个值,而age的类型为int,weight的类型为double,都为基本数据类型,所以值直接存放堆中。

    5.当程序执行到 cat.say() ;方法时,会先到栈区找到cat这个引用变量(这个变量存的是对象的引用地址),然后根据该地址值在堆内存中找到 new Cat() 对象里面的say()方法进行调用,在调用say()方法时,会在栈区开辟一块空间进行运行。

    6.在方法体void say()被调用完成后,就会立刻马上从栈内弹出(出站 ),最后,在main()函数完成后,main()函数也会出栈

    本文为joshua317原创文章,转载请注明:转载自joshua317博客 Java 类和对象在内存中的表现形式,栈、堆、方法区、常量池 - joshua317的博客

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

    千次阅读 2021-03-10 01:42:56
    转载自http://blog.csdn.net/hbhhww/article/details/8152838...Java的是一个运行时数据,类的对象从中分配空间。这些对象通过new、newarray、anewarray和multianewarray等指令建立,它们不需要程序代码来显式的...
  • 浅谈堆、堆区区的概念和区别

    万次阅读 多人点赞 2019-10-21 15:45:15
    以前小编我对于这几个名词真的是分不清,感觉好像都一样,因为概念很抽象,不知道大家有没有这样觉得,所以我觉得有必要要对它进行区分下,让大家对它起码有宏观的认识。 一、区别 注:首先可以分为两种,...
  • 对于代码: ...如果这个语句出现函数内部,那么它就在栈上创建对象。 如果这个语句不是函数内部,而是作为一个类的成员变量,则取决于这个类的对象是如何分配的。 class Class { Object obj; };...
  • String类型的对象,是保存在堆还是在栈里呢? Java的实现中,new出来的String对象一般是放在中的。 如果是 String s =“xxx”; 这种,那就是放在常量池中. JDK6将常量池放在方法中。 方法此时也是持久代。...
  • Java中对象存储位置 -

    千次阅读 2021-03-09 15:59:45
    1. (stack)与(heap)都是Java用来Ram中存放数据的地方。与C++不同,Java自动管理,其对象存储位置由系统自然分配,程序员不能直接地设置。2. 的优势是,存取速度比要快,仅次于直接位于CPU中的...
  • 一文搞懂区和堆区

    千次阅读 2021-02-08 12:09:01
    C++ 中,并不强调如何在堆区区分配内存。它是用自动存储周期和动态存储周期来区分的。本地变量是自动存储周期,编译器会把它存在区。而对象是动态分配内存的(用 new 关键字创建),存在堆区没有垃圾...
  • C++程序的内存分区模型-区&堆区

    千次阅读 多人点赞 2022-03-29 10:50:03
    区:由编译器自动分配释放,存放函数的参数值,局部变量等(由编译器管理其“生死”) 堆区:由程序员分配释放,若程序员不释放,程序结束后由操作系统回收 new操作符
  • Java中对象到底存在还是栈

    千次阅读 2020-07-30 14:50:02
    创建一个对象的时候,到底是在栈中分配还是在堆中分配需要看2个方面:对象类型和Java中存在的位置 1.如果是基本数据类型,byte、short、int、long、float、double、char,如果是方法中声明,则存储在栈中,其它...
  • 创建对象的内存是分配在堆还是栈上面?大部分童鞋的回答是这样的:“肯定分配在堆内存的嘛,内存的那是java属于子线程专用的内存空间”
  • 区和堆区

    千次阅读 2021-11-07 14:57:32
    区 用来存放程序运行过程中的局部变量。堆区 用来存储new关键字创建的对象 (数组是对象类型的)。 综上所述,可知区(局部变量) 存放的是 堆区(new对象的存储地址)
  • 先说结论,放在中只要是成员变量,所在的类被实例化,不管是不是基础类型都会放在中第一个结论就是错的基本数据类型是放在还是放在中,这取决于基本类型声明的位置。第一种: 方法中声明的变量,即该变量是...
  • 我们使用基本的数据类型或者自定义数据类型创建³³变量或者对象的时候的英文在堆还是栈上? 在堆上与上有什么区别? 在对象之间赋值的时候,什么时候需要重载“=”号,或者使用memcopy? 的区别 ...
  • Java中创建的局部变量等是存放在栈区的,而数组是存放在堆区的,那些new出来的对象也大多存放于堆区
  • C++只在栈上实例化对象

    千次阅读 2019-09-11 20:46:44
    C++如何让类对象只能在堆)上分配空间 一般情况下写一个类都是可以采用new在堆上分配空间,或直接采用 类名+对象名 的方式在栈上分配空间。但有时候,如果想让一个类只能在栈上或者上分配空间,又该怎么实现...
  • 时间:2019-07-05 来源:网络资源 标签:中歌会 问题中的String指的应该是java中的String吧。这里给出的回答针对java。String是一个不可变的...String本身作为一个对象,必然是在堆上的,而String中的内容char[] va...
  • 这要根据对象的类型和对象在Java类中的位置来判断 对象类型 对象在Java类中的位置 ...可以知道对象都是存在上的,其他地方拥有的只不过是对象的一个引用,而基础数据类型则根据Java类中...
  • 堆区区的区别

    千次阅读 2021-08-19 08:52:56
    1、是限定仅仅表尾进行插入和删除操作的线性表,把允许插入和删除的一端称之为栈顶,另外一端称之为底。特点:后进先出,称之为后进先出线性表。 2、是一种经过排序的树形数据结构,每一个节点都有一...堆区
  • Person p =new Person(“张三”,20); 这样的,我可不可以这样理解new Person(“张三”,20)在堆内存中创建,分配...Person p 在栈内存中创建,然后把内存中的内存地址付给内存中的p变量 我这样理解有错误吗
  • Java对象与引用变量,在堆区区的存放原理 Student stu; //1、在栈内存里面开辟了空间给引用变量stu stu = new Student(); //2、new Student()堆内存里面开辟了空间给Student类的对象,只是这个对象还没有...
  • c++的成员变量是在堆还是栈区

    千次阅读 2018-05-11 15:51:33
    成员变量并不能决定自身的存储空间位置。决定存储位置的对象的创建方式。即:如果对象是函数内的非静态局部变量,则对象对象的成员变量保存在栈区。...如果对象是new出来的,则对象对象的成员变量保存在堆区。...
  • 内存、内存、方法

    千次阅读 2019-07-18 16:25:51
    一、Java内存管理 Java程序运行虚拟机(JVM)上,JVM相当于Java程序和操作系统之间的桥梁,Java程序通过JVM实现了平台无关性,可以跨平台操作。Java虚拟机执行Java程序的过程...这里主要介绍三种内存内存、...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 326,609
精华内容 130,643
热门标签
关键字:

对象在栈区还是堆区