• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
学习笔记
Misaka的学习笔记
博客园    首页    新随笔    联系   管理    订阅  订阅
c#学习笔记--------------堆,栈,静态存储区

参考文章:

https://www.zditect.com/article/59283897.html

https://www.cnblogs.com/simonLiang/p/5729649.html

程序所有的数据,也就是所有的变量,都是存储在内存中的。

可编程内存基本上分为几大部分:栈区、堆区和静态存储区。

栈(stack)

  保存局部变量和局部函数的,函数结束,其局部变量和参数的生命就结束了(当然是不包括static变量)。即释放了栈的空间(顺便提一下:栈特点为后进先出的!)。

  栈的分配运算内置于处理器的指令集中,效率极高,但是分配的内存容量有限。

栈的特征:

数据只能从栈的顶端插⼊和删除

把数据放⼊栈顶称为⼊栈(push) 、

从栈顶删除数据称为出栈(pop)

内存中的栈,是由系统管理(.Net框架)。

堆(heap)

  也称动态内存分配区。

       堆是⼀块内存区域,与栈不同,堆⾥的内存能够以任意顺序存⼊和移除

  程序员向操作系统申请的内存空间。程序在运行的时候用malloc或new申请任意大小的内存,程序员自己负责在适当的时候用free或delete释放内存。动态内存的生存期可以由我们决定,如果我们不释放内存,程序将在最后才释放掉动态内存。可存储较大的数据。

  堆是以匿名方式保存的,只能通过指针访问,安全性最高,由程序员分配与释放,自由度最高!

 GC Garbage Collector垃圾回收器

CLR的GC就是内存管理机制,我们写程序不需要关⼼内存的使⽤,因为这些都是CLR帮 我们做了

静态存储区

  内存在程序编译的时候已经分配好。这块内存在整个程序的运行期间都存在。

  主要存放静态数据、全局数据和常量。

堆栈的不同

(1)内存申请方式的不同:如果函数中声明一个局部变量int a,系统会自动在栈中为a 开辟空间;而堆空间需要程序员自己申请,还需要指明变量的大小。

(2)系统响应的不同:只要栈的剩余空间大于所申请的空间,系统将为程序提供内存,否则提示overflow,栈溢出;而对于堆,系统在收到申请空间的要求后,遍历操作系统用于记录内存空间地址的链表,当找到一个空间大于所申请空间的堆结点后,就会将该结点从记录内存空闲地址的链表中删除。并将该结点的内存分配给程序,然后在这块内存区域的首地址处记录分配的大小。这样在使用delete来释放的时候,delete才能正确识别并删除该内存区域的所有变量。另外,申请的内存空间与堆结点的内存空间不一定相等,这是系统个会自动将堆结点上多出来的那一部分内存空间回收到空闲链表中。

(3)空间大小的不同:栈是一块连续的区域,大小在编译时就确定的常数,有系统预先根据栈顶的地址和栈的最大容量定义好的;堆是不连续的区域,各块区域由链表串联起来。串联起来的内存空间叫作堆!上限是由系统的虚拟内存来定的。

(4)执行效率的不同:栈比较快,由系统自动分批;堆速度较慢,且容易产生内存碎片。

(5)执行函数时的不同:函数调用时,第一个进栈的是被调函数下一行的内存地址(栈的先进后出)。其次是函数的参数,假如参数duo与一个,那么次序是从右往左。最后才是函数的局部变量。

栈空间⽐较⼩,但是读取速度快

堆空间⽐较⼤,但是读取速度慢

数组存储在c#中的堆或堆栈中

  •  C#中的ValueType数组去堆还是栈?在C#中有两个地方可以存储一个对象——堆和栈。如果数组中的元素超过 1000 个,则在堆栈上分配的对象仅在堆栈内可用,则存储在 LOH 上。你可以在 C# 中的数组中存储不同的类型吗?
  •  C数组是存储在堆栈还是堆中? 一个整数数组分配在堆上,不多也不少。myIntegers 引用分配整数的部分的开头。该引用位于堆栈上。Array 是一种引用类型,直接从 System.Object 派生,因此它是在堆上收集的垃圾。如果我有一个 Int32 数组,那么就可以了。
  •  C数组是存储在堆栈中还是堆中?你可以在C#中存储不同类型的数组吗?在堆上分配了一个整数数组,仅此而已。myIntegers 引用分配整数的部分的开头。该引用位于堆栈上。
  •  NET 中的内存 - 去哪里 Array 是一种引用类型,直接从 System.Object 派生,因此它是在堆上收集的垃圾。如果我有一个 Int32 数组,那么 C# 中的堆栈和堆内存有什么区别?
  •  NET 中的内存 - 去哪里 在堆上分配一个整数数组,仅此而已。myIntegers 引用分配整数的部分的开头。该引用位于堆栈上。Array 是一种引用类型,直接从 System.Object 派生,因此它是在堆上收集的垃圾。如果我有一个 Int32 数组,那么就可以了。
  •  NET 中的 C# Heap(ing) Vs Stack(ing) - 第一部分 C# 中的堆栈和堆内存有什么区别?堆栈是一个内存数组。它是一种后进先出 (LIFO) 数据结构。只能从堆栈顶部添加和删除数据。将数据项放在堆栈顶部称为将数据项推入堆栈。
  •  C# Heap(ing) Vs Stack(ing) 在 .NET - 第一部分中 Array 是一种引用类型,直接从 System.Object 派生,因此它是在堆上收集的垃圾。如果我有一个 Int32 数组,那么 C# 中的堆栈和堆内存有什么区别?
  •  数组、堆和栈以及值类型 栈是内存数组。它是一种后进先出 (LIFO) 数据结构。只能从堆栈顶部添加和删除数据。将数据项放在堆栈顶部称为将数据项推入堆栈。在本文中,您将了解 Stack v/s Heap Memory - C#。堆栈内存,堆内存。什么是栈和堆?它是一个内存数组。在其中可以按任何顺序存储和删除数据。内存是如何管理的?
  •  数组,堆和堆栈以及值类型 C#中的堆栈和堆内存有什么区别?堆栈是一个内存数组。它是一种后进先出 (LIFO) 数据结构。只能从堆栈顶部添加和删除数据。将数据项放在堆栈顶部称为将数据项推入堆栈。
  •  堆栈与堆内存 - C#在本文中,您将了解 Stack v/s Heap Memory - C#。堆栈内存,堆内存。什么是栈和堆?它是一个内存数组。在其中可以按任何顺序存储和删除数据。内存是如何管理的?在 C# 中有两个地方可以存储对象——堆和栈。分配在堆栈上的对象只能在堆栈帧(方法的执行)内使用,而分配在堆上的对象可以从任何地方访问。问:哪些对象分配在栈上,哪些对象分配在堆上?

c#中对象是如何存储在内存中的

  •  NET 中的内存 - 去哪里概念是相同的,但有区别,因为您确实可以在不安全的 C# 代码中拥有指针。如果您抓住一个指向对象的指针,并且该对象移动,则您的指针指向任意内存空间。但是,对象引用被保留。对于年龄问题。它存储在对象本身中,在结构中占据 32 位 - 不是指向 int32 的引用/指针 在堆栈上分配的变量直接存储到内存中,它允许随机分配或释放对象order..
  •  对象如何存储在内存中?堆栈以一种非常简单和统一的方式工作,因为它限制了如何使用该内存以及对象存储在 C# 中的时间长度在 C# 类、对象、数组、索引器、接口和字符串中,所有类型都使用指针存储在内存中或对对象的引用,但是
  •  对象如何存储在内存中?分配在堆栈上的变量直接存储到内存中,它允许以随机顺序分配或释放对象。堆栈以非常简单和统一的方式工作,因为它限制了您如何使用该内存以及对象存储在
  •  C# 内存管理在 C# 类中,对象、数组、索引器、接口和字符串都是存储在内存中的类型,带有指向对象的指针或引用,但是,我们可以说普通变量,如 int、Boolean、double float 存储在堆栈和对象中存储在堆上。让我们尝试理解值类型和引用类型。现在根据上面的例子,两个变量 a 和 b 都将分配自己的内存块,并且更改 b 的值不会影响 a 的值,反之亦然。
  •  C# 内存管理堆栈以一种非常简单和统一的方式工作,因为它限制了您如何使用该内存以及对象存储在 C# 中的类、对象、数组、索引器、接口和字符串中的所有类型都存储了多长时间在内存中带有指向对象的指针或引用,但是
  •  NET 中的 C# Heap(ing) Vs Stack(ing) - 第一部分 但是,我们可以说普通变量,如 int、Boolean、double float 存储在堆栈上,而对象存储在 Heap 上。让我们尝试理解值类型和引用类型。现在根据上面的例子,两个变量 a 和 b 都将分配自己的内存块,并且更改 b 的值不会影响 a 的值,反之亦然。找到你感兴趣的类型,看看它是否真的是使用内存的东西 为你的特定类型转储堆 (!DumpHeap -type MyNameSpace.MyType) 找到你认为应该释放的对象的内存地址,看看它是否在某处“扎根”。
  •  NET 中的 C# Heap(ing) Vs Stack(ing) - 第一部分在 C# 类中,对象、数组、索引器、接口和字符串都是存储在内存中的类型,带有指向对象的指针或引用,但是,我们可以说 int、Boolean、double float 等普通变量存储在堆栈上,而对象存储在堆上。让我们尝试理解值类型和引用类型。现在根据上面的例子,两个变量 a 和 b 都将分配自己的内存块,并且更改 b 的值不会影响 a 的值,反之亦然。
  •  六个重要的 .NET 概念:堆栈、堆、值类型、引用、找到你感兴趣的类型,看看它是否真的是使用内存的东西 为你的特定类型转储堆 (!DumpHeap -type MyNameSpace.MyType) 找到你认为应该释放的对象的内存地址,看看它是否在某处“扎根”。它是一个内存数组。它是一种 LIFO(后进先出)数据结构。在其中只能从其顶部添加和删除数据。它是一块内存区域,其中分配了块以存储某些类型的数据对象。
  •  NET 的六个重要概念:堆栈、堆、值类型、引用。 但是,我们可以说普通变量(如 int、Boolean、双浮点)存储在堆栈上,而对象存储在堆上。让我们尝试理解值类型和引用类型。现在根据上面的例子,两个变量 a 和 b 都将分配自己的内存块,并且更改 b 的值不会影响 a 的值,反之亦然。

关于栈stack常用的方法

Stack<T>

堆栈(Stack)代表了一个后进先出的对象集合。

当您需要对各项进行后进先出的访问时,则使用堆栈。

当您在列表中添加一项,称为推入元素,当您从列表中移除一项时,称为弹出元素。

Stack是一种特殊的集合类型,

以LIFO方式(后进先出)存储元素。

C#包括泛型Stack<T>和非泛型Stack集合类。

建议使用泛型Stack<T>集合。

Stack 类的方法和属性

属性  

Count (获取 Stack 中包含的元素个数。)

方法

public virtual void Clear();
从 Stack 中移除所有的元素。

public virtual bool Contains( object obj );
判断某个元素是否在 Stack 中。

public virtual object Peek();
返回在 Stack 的顶部的对象,但不移除它。

public virtual object Pop();
移除并返回在 Stack 的顶部的对象。

public virtual void Push( object obj );
向 Stack 的顶部添加一个对象。

public virtual object[] ToArray();
复制 Stack 到一个新的数组中。

下面的实例演示了堆栈(Stack)的使用:

创建堆栈

Stack<int> myStack = new Stack<int>();
myStack.Push(1);
myStack.Push(2);
myStack.Push(3);
myStack.Push(4);

foreach (var item in myStack)
     Console.Write(item + ","); //打印4,3,2,1,

使用示例:

using System;
using System.Collections;

namespace CollectionsApplication
{
    class Program
    {
        static void Main(string[] args)
        {
            Stack st = new Stack();

            st.Push('A');
            st.Push('M');
            st.Push('G');
            st.Push('W');
           
            Console.WriteLine("Current stack: ");
            foreach (char c in st)
            {
                Console.Write(c + " ");
            }
            Console.WriteLine();
           
            st.Push('V');
            st.Push('H');
            Console.WriteLine("The next poppable value in stack: {0}",
            st.Peek());
            Console.WriteLine("Current stack: ");          
            foreach (char c in st)
            {
               Console.Write(c + " ");
            }
            Console.WriteLine();

            Console.WriteLine("Removing values ");
            st.Pop();
            st.Pop();
            st.Pop();
           
            Console.WriteLine("Current stack: ");
            foreach (char c in st)
            {
               Console.Write(c + " ");
            }
        }
    }
}

 

关于队列Queue的属性常用方法

System.Collections.Queue类表示对象的先进先出集合,存储在 Queue(队列) 中的对象在一端插入,从另一端移除。

Queue队列就是先进先出。它并没有实现 IList,ICollection。所以它不能按索引访问元素,不能使用Add和Remove。下面是 Queue的一些方法

  1.   Enqueue():在队列的末端添加元素
  2.   Dequeue():在队列的头部读取和删除一个元素,注意,这里读取元素的同时也删除了这个元素。如果队列中不再有任何元素。就抛出异常
  3.   Peek():在队列的头读取一个元素,但是不删除它
  4.   TrimExcess():重新设置队列的容量,因为调用Dequeue方法读取删除元素后不会重新设置队列的容量。
  5.   Contains():确定某个元素是否在队列中
  6.   CopyTo():把元素队列复制到一个已有的数组中
  7.   ToArray():返回一个包含元素的新数组

属性

  1.   Count:返回队列中的元素个数

使用示例:

class Program 
{ 
    static void Main(string[] args) 
    { 
        //创建一个队列 
        Queue myQ = new Queue(); 
        myQ.Enqueue("The");//入队 
        myQ.Enqueue("quick"); 
        myQ.Enqueue("brown"); 
        myQ.Enqueue("fox"); 
        myQ.Enqueue(null);//添加null 
        myQ.Enqueue("fox");//添加重复的元素 
 
        // 打印队列的数量和值 
        Console.WriteLine("myQ"); 
        Console.WriteLine("\tCount:    {0}", myQ.Count); 
 
        // 打印队列中的所有值 
        Console.Write("Queue values:"); 
        PrintValues(myQ); 
 
        // 打印队列中的第一个元素,并移除 
        Console.WriteLine("(Dequeue)\t{0}", myQ.Dequeue()); 
 
        // 打印队列中的所有值 
        Console.Write("Queue values:"); 
        PrintValues(myQ); 
 
        // 打印队列中的第一个元素,并移除 
        Console.WriteLine("(Dequeue)\t{0}", myQ.Dequeue()); 
 
        // 打印队列中的所有值 
        Console.Write("Queue values:"); 
        PrintValues(myQ); 
 
        // 打印队列中的第一个元素 
        Console.WriteLine("(Peek)   \t{0}", myQ.Peek()); 
 
        // 打印队列中的所有值 
        Console.Write("Queue values:"); 
        PrintValues(myQ); 
 
        Console.ReadLine(); 
 
    } 
 
    public static void PrintValues(IEnumerable myCollection) 
    { 
        foreach (Object obj in myCollection) 
            Console.Write("    {0}", obj); 
        Console.WriteLine(); 
    } 
}

 

 

 

 
 
 
posted on 2023-08-07 17:55  我们打工人  阅读(1027)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3