了解变量如何在内存上分配存储(一)

1、前言

在编写代码中,我们经常回调用这样或那样的方法(函数),但是我们真的了解各种参数类型在内存上市如何分配的么?不见得,至少在这之前我就不是很了解。我们也许认为这只是一个很小的问题,觉得知道方法是做什么的、会调用方法就行,所以就忽略了这一点。下面就了解一下方法中的参数是如何在内存上分配的。如有不妥之处,还请各位大牛指点。

2、值类型与引用类型的分配

一般来说,值类型是分配在栈中,而引用类型则在堆中分配存储单元。栈在编译的时候就分配好内存空间,在代码中有栈的明确定义,而堆是程序运行中动态分配的内存空间,可以根据程序的运行情况动态地分配内存的大小。因此,值类型总是在内存中占用一个预定义的字节数(比如,int占用4个字节,即32位)。当声明一个值类型变量时,会在栈中自动分配此变量类型占用的内存空间,并存储这个变量所包含的值。.NET会自动维护一个栈指针,它包含栈中下一个可用内存空间的地址。栈是先入后出的,栈中最上面的变量总是比下面的变量先离开作用域。当一个变量离开作用域时,栈指针向下移动被释放变量所占用的字节数,仍指向下一个可用地址。注意,值类型的变量在使用时必须初始化。

而引用类型的变量则在栈中分配一个内存空间,这个内存空间存储的是对另一个内存位置的引用,这个位置是托管堆中的一个地址,即存放此变量实际值的地方。.NET也自动维护一个堆指针,它包含堆中下一个可用内存空间的地址,但堆不是先入后出的,堆中的对象不人在程序的一个预定义点离开作用域,为了在不使用堆中分存的内存时将它释放,.NET将定期执行垃圾收集。垃圾收集器递归地检查应用程序中所有的对象引用,当发现引用不再有效的对象使用的内存无法从程序中访问时,该内存就可以回收(除了fixed关键字固定在内存中的对象外)。

但值类型在栈上分配内存,而引用类型在托管堆上分配内存,却只是一种笼统的说法。下面是网上找到的更详细准确地描述:

1、对于值类型的实例,如果作为方法中的局部变量,则被创建在线程栈上;如果该实例做为类类型的成员,则作为类型成员的一部分,连同其他类型字段都存放在托管堆上;
2、引用类型的实例创建在托管堆上,如果其字节小于85000byte,则直接创建在托管堆上,否则创建在LOH(Large Objet Heal)上。

关于引用类型的存储,我觉得上面的第二点说的还是不够详细,如果引用类型不是一个类类型的成员,那么它的存储被分为两部分,一部分是引用部分,存储在栈上并指向具体的堆地址,另一部分是实际的数据部分,存储在堆上;如果引用类型是一个类类型的成员,那么无论是引用部分还是数据部分,都会作为类类型的实例存储在堆上。

1 public class MyClass
2 {
3     private int i;    //即使变量i是值类型,但它作为MyClass(引用类型)实例的一部分,与MyClass的实例一起被创建在GC堆上
4     public MyClass()
5     {
6         int j = 0;    //作为局部变量,j的实例被创建在执行这段代码的线程栈上
7     }
8 }

3、数组中值类型和引用类型的内存分配

数组分为值类型和引用类型,见下面的代码段:

 1 public class Person
 2 {
 3     private int age;
 4     private string name;
 5
 6     public int Age
 7     {
 8         get;
 9         set;
10     }
11
12     public string Name
13     {
14         get;
15         set;
16     }
17 }
1 Person[] person=new Person[5];//引用类型数组
2 int[] num=new int[5];//值类型数组

数组也是引用类型,所以数组类型的变量被分配在堆上。

对于上述int类型(简单的值类型的数组),每个数组成员是一个引用(指针),引用到栈上的空间(因为值类型变量的内存分配在栈上);

对于上述Person类类型(引用类型,类类型的数组),每个数组成员仍是一个引用(指针),引用到堆上的空间(因为类的实例的内存分配在堆上)

4、总结

最近在看这方面的资料,总觉得还是写出来会加深印象,另一方面,可以为初学者提供思路。以上是关于值类型和引用类型的内存分配方式,如果有什么不对的地方,请各位大牛指出,我会学习并作相应修改。

我会在下一篇介绍关于具体的方法参数的内存分配方式,谢谢大家!!

时间: 2024-10-10 01:10:19

了解变量如何在内存上分配存储(一)的相关文章

C/C++中变量的分配和在内存中的存储方式

操作系统与C语言中的堆栈及其区别 CSDN C/C++ 一个由C/C++编译的程序占用的内存分为以下几个部分 1. 栈区(stack)- 由编译器自动分配释放,存放函数的参数名,局部变量的名等.其操作方式类似于数据结构中的栈. 2. 堆区(heap)- 由程序员分配释放,若程序员不释放,程序结束时可能由OS回收.注意它与数据结构中的堆是两回事,分配方式倒是类似于链表. 3. 全局区(静态区)(static)-全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域, 未初始化的

【C/C++学院】0819-/类的成员函数与const-mutable /构造与析构/拷贝构造deletedefault以及深浅拷贝/静态成员函数成员变量类在内存的存储默认参数/友元类以及友元函数

类的成员函数与const-mutable 成员函数 Fushu.h #pragma once #include <iostream> class fushu { public: int x; int y; public: fushu(); ~fushu(); void show(); inline void showall(int x, int y);//显式内联 void setxy(int x, int y);//编译器优化,默认隐式内联 void show(int x, int y);

智能合约从入门到精通:Solidity语法之内存变量的布局和状态变量的存储模型

简介:在前面我们已经讲过Solidity语言的一些语法内容,在矩阵元JUICE开放平台的JIDE开发时,一定要注意Layout in Memory和Layout of State Variables in Storage,即内存变量的布局和状态变量的存储模型.内存变量的布局(Layout in Memory) Solidity预留了3个32字节大小的槽位: 0-64:哈希方法的暂存空间(scratch space) 64-96:当前已分配内存大小(也称空闲内存指针(free memory poi

变量在内存中的存储方式-----“大端”和“小端”

"大端"和"小端"可以追溯到1726年的Jonathan Swift的<格列佛游记>,其中一篇讲到有两个国家因为吃鸡蛋究竟是先打破较大的一端还是先打破较小的一端而争执不休,甚至爆发了战争.1981年10月,Danny Cohen的文章<论圣战以及对和平的祈祷>(On holy wars and a plea for peace)将这一对词语引入了计算机界(<程序设计实践>第9章).这么看来,所谓大端和小端,也就是big-endia

在地址0上分配内存

在 NULL 地址上分配内存看似是不可行的 ,因为对于内存分配函数 NTSTATUS ZwAllocateVirtualMemory(   _In_     HANDLE ProcessHandle,   _Inout_  PVOID *BaseAddress,   _In_     ULONG_PTR ZeroBits,   _Inout_  PSIZE_T RegionSize,   _In_     ULONG AllocationType,   _In_     ULONG Protec

QList介绍(QList比QVector更快,这是由它们在内存中的存储方式决定的。QStringList是在QList的基础上针对字符串提供额外的函数。at()操作比操作符[]更快,因为它不需要深度复制)非常实用

FROM:http://apps.hi.baidu.com/share/detail/33517814 今天做项目时,需要用到QList来存储一组点.为此,我对QList类的说明进行了如下翻译. QList是一种表示链表的模板类.QList<T>是Qt的一种泛型容器类.它以链表方式存储一组值,并能对这组数据进行快速索引,还提供了快速插入和删除等操作.QList.QLinkedList和QVector提供的操作极其相似:* 对大多数操作来说,我们用QList就可以了.其API是基于索引(inde

堆栈详解(数据与内存中的存储方式)

转自:http://www.360doc.com/content/11/0428/18/6580811_112988089.shtml char* r = "hello word!"; char b[]="hello word!"*r = 'w'; *b='w'; 其实应该是语法错误,可是VC++6.0没有警告或者错误,r指向的是文字常量区,此区域是编译的时候确定的,并且程序结束的时候自动释放的, *r = 'w';企图修改文字常量区引起错误,b的区别在于其空间是在

什么变量在堆内存里存放,什么变量在栈内存里存放

什么变量在堆内存里存放,什么变量在栈内存里存放 堆和栈的区别 (stack and heap) 一般认为在c中分为这几个存储区 1栈 - 有编译器自动分配释放 2堆 - 一般由程序员分配释放,若程序员不释放,程序结束时可能由OS回收 3全局区(静态区),全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域. 程序结束释放. 4另外还有一个专门放常量的地方. - 程序结束释放 在函数体中定义的变量通常是在栈上,用mal

(转)Java 内存区域分配和垃圾回收(GC)机制

Java垃圾回收概况 Java GC(Garbage Collection,垃圾收集,垃圾回收)机制,是Java与C++/C的主要区别之一,作为Java开发者,一般不需要专门编写内存回收和垃圾清理代 码,对内存泄露和溢出的问题,也不需要像C程序员那样战战兢兢.这是因为在Java虚拟机中,存在自动内存管理和垃圾清扫机制.概括地说,该机制对 JVM(Java Virtual Machine)中的内存进行标记,并确定哪些内存需要回收,根据一定的回收策略,自动的回收内存,永不停息(Nerver Stop