1.创建一个对象

  一个对象的创建过程主要分为内存分配和初始化两个环节。在.NET中CLR管理的内存区域主要有三部分:栈、GC堆、LOH堆,栈主要用来分配值类型数据。它的管理是有系统控制的,而不是像GC堆那样是由GC控制的。当线程执行完值类型实例所在方法后,这块空间将会被自动释放,一般栈的执行效率高不过容量有限。GC堆用来分配小对象实例,它是由GC完全控制内存的分配和回收。LOH堆则是为大对象实例准备的,它不会被压缩且只在GC完全回收时才会回收。在IL中可以看到newobj、ldstr(创建string对象)、newarr(用于分配新的数组对象)、box(装箱)等常见的创建对象的指令。当然在堆上也存在值类型,比如值类型作为类的字段时,它将存储在堆中的实例对象空间,还有装箱时也会让堆上存在值类型。好了接下来我们来看看创建一个对象的内存分配,现在有一个Person类和Student类。那么这句Student s = new Student() { studentId = 2, Id = 4 };执行完后s对象就被创建了,下面我画了张图来说明创建一个对象时内存的分配,其中s对象还有同步索引块与类型对象指针我没有画出来。

 public class Person
{
public int Id;
public void Eat()
{
Console.WriteLine("Eat Pear");
}
} public class Student:Person
{
public int studentId;
public void GotoSchool()
{
Console.WriteLine("Go to School");
}
}

 2.父类对象指向子类

  我们在写程序时为了实现多态一般都会使用父类对象指向子类。那么当我写入Person p=new Student();时便在堆中创建了一个子类对象,下面是关于父类对象指向子类的内存分配图。我在Person中添加了虚方法和抽象方法,并在Student子类重写了方法。从图中可以看出一旦子类重写了父类的虚方法或抽象方法,则Person方法表中的2个方法将会被子类覆盖,我们可根据它来实现多态。另外在Student方法表中还有一个new void Eat()方法,不过它是无法被p调用的因为此时的new Eat()属于子类。也就是说除了被覆盖的方法外,p只能调用Person方法表中的方法,如果找不到则会继续寻找Person父类的方法直到object。注意是不会往回找的,它不会去Student方法表中寻找方法。

public  abstract class Person
{
public int Id;
public void Eat()
{
Console.WriteLine( "在吃梨");
}
public virtual void Walk()
{
Console.WriteLine("在散步");
}
//抽象方法只能在抽象类中声明,因此要在Person前加abstract,且只能声明并必须在子类中实现。
public abstract void Run();
}
public class Student:Person
{
public int studentId;
public void GotoSchool()
{
Console.WriteLine("Go to School");
} public new void Eat()
{
Console.WriteLine("学生 吃苹果");
}
public override void Walk()
{
Console.WriteLine("学生 在散步");
}
public override void Run()
{
Console.WriteLine("学生 在跑步");
}
}

3.指向孙类对象

  现在我再添加一个Student的子类James,从上一个例子中已经知道只有override关键字重写的方法父类才会调用,因此我将普通方法全部删除。执行代码为Person p = new James() { name = "James", studentId = 2, Id = 4 };代码和内存分配图如下,为了突出重点,图中我就没有画字段了。从结果可以看到SayHi方法最后是被孙类的SayHi覆盖了,从这里可以看出继承的传递性!

 public  abstract class Person
{
public int Id;
public virtual void Eat()
{
Console.WriteLine( "在吃梨");
}
public virtual void Walk()
{
Console.WriteLine("在散步");
}
//抽象方法只能在抽象类中声明,因此要在Person前加abstract,且只能声明并必须在子类中实现。
public abstract void Run();
public virtual void SayHi()
{
Console.WriteLine("人说:你好!");
}
}
public class Student:Person
{
public int studentId;
public virtual void Eat()
{
Console.WriteLine("学生 在吃梨");
}
public override void Walk()
{
Console.WriteLine("学生 在散步");
}
public override void Run()
{
Console.WriteLine("学生 在跑步");
}
}
 public class James:Student
{
public string name;
public override void Eat()
{
Console.WriteLine("James 在吃梨");
}
public override void Walk()
{
Console.WriteLine("James 在散步");
}
public override void Run()
{
Console.WriteLine("James 在跑步");
}
public override void SayHi()
{
Console.WriteLine("James说:你好!");
}
}

声明:本文原创发表于博客园,作者为方小白,如有错误欢迎指出 。本文未经作者许可不许转载,否则视为侵权。

C#基础之内存分配的更多相关文章

  1. java基础:内存分配(上)

    java执行中的内存分区: 1.代码域:存放代码 2.数据域:存放静态的数据 3.栈:存放局部变量 4.堆:存放成员变量 (ps:局部变量是类中方法体中申明的变量,只在这个方法中有效:成员变量是类中方 ...

  2. Spark Tungsten揭秘 Day3 内存分配和管理内幕

    Spark Tungsten揭秘 Day3 内存分配和管理内幕 恭喜Spark2.0发布,今天会看一下2.0的源码. 今天会讲下Tungsten内存分配和管理的内幕.Tungsten想要工作,要有数据 ...

  3. JAVA基础-栈与堆,static、final修饰符、内部类和Java内存分配

    Java栈与堆 堆:顺序随意 栈:后进先出(Last-in/First-Out). Java的堆是一个运行时数据区,类的对象从中分配空间.这些对象通过new.newarray.anewarray和mu ...

  4. Java基础-Java中的内存分配与回收机制

    Java基础-Java中的内存分配与回收机制 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一. 二.

  5. 数据结构基础(1)--数组C语言实现--动态内存分配

    数据结构基础(1)--数组C语言实现--动态内存分配 基本思想:数组是最常用的数据结构,在内存中连续存储,可以静态初始化(int a[2]={1,2}),可以动态初始化 malloc(). 难点就是数 ...

  6. JVM基础知识2 垃圾收集器与内存分配策略

    如何判断堆中的哪些对象可以被回收 主流的程序语言都是使用根搜索算法(GC Roots Tracing)判定对象是否存活 基本思路是:通过一系列名为“GC Roots”的对象作为起点,从这些节点开始向下 ...

  7. JVM基础学习(二):内存分配策略与垃圾收集技术

    Java与C++之间有一堵由内存动态分配和垃圾收集技术所围成的高墙,墙外面的人想进去,墙里面的人却想出来 垃圾收集概述 Java内存模型中的堆和方法区是垃圾收集技术所需要关注的终点,因为其他的区域会跟 ...

  8. Java学习之旅基础知识篇:数组及引用类型内存分配

    在上一篇中,我们已经了解了数组,它是一种引用类型,本篇将详细介绍数组的内存分配等知识点.数组用来存储同一种数据类型的数据,一旦初始化完成,即所占的空间就已固定下来,即使某个元素被清空,但其所在空间仍然 ...

  9. 数据结构基础——指针及动态内存分配(malloc)

    一.指针 C语言中的指针是一种数据类型,比如说我们用int *a;就定义了一个指针a,它指向一个int类型的数.但是这个指针是未初始化的,所以,一般的,我们都在创建指针时初始化它,以免出错,在还不吃的 ...

随机推荐

  1. Spring web.xml配置文件解析

    概要解析

  2. apache CXF wsdl2java工具的使用

    cxf的wsdl2java命令和JDK的wsimport命令的区别和使用 JDK提供了一个wsimport.exe的命令,主要是用于将WebService生成客户端代码,然后好调用WebService ...

  3. Linux常用压缩和解压命令

    .tar 解包 tar xvf filename.tar.tar 打包 tar cvf filename.tar dirname.gz 解压1 gunzip filename.gz.gz 解压2 gz ...

  4. 虚拟机ping不通主机,但是主机可以ping通虚拟机(转载)

    我在Windows7系统安装了虚拟机,通过虚拟机安装了Ubuntu13.04,我设置的主机与虚拟机的连接方式是桥接,安装好后,发现虚拟机ping不通主机,但是主机可以ping通虚拟机. 我的操作是:关 ...

  5. 文件输入流 FileInputStream类 文件输出流FileOutputStream ---转载

    转载自---http://blog.csdn.net/hguisu/article/details/7418161 111:文件输入流: FileInputStream可以使用read()方法一次读入 ...

  6. EXCEL IF 函数 模糊查询

    A列都是产品名,比如衬衫,长袖衬衫,短袖衬衫,短裙,长裙 搜索A列的产品名,凡是含有“衬衫”的一律在B列对应行输出“衬衫”,凡是含有“裙”字的一律输出“裙子”在B列对应行,请教一下怎么写函数,本来用I ...

  7. ZOJ 3829 Known Notation --贪心+找规律

    题意:给出一个字符串,有两种操作: 1.插入一个数字  2.交换两个字符   问最少多少步可以把该字符串变为一个后缀表达式(操作符只有*). 解法:仔细观察,发现如果数字够的话根本不用插入,数字够的最 ...

  8. UVA 11573 Ocean Currents --BFS+优先队列

    采用优先队列做BFS搜索,d[][]数组记录当前点到源点的距离,每次出队时选此时eng最小的出队,能保证最先到达的是eng最小的.而且后来用普通队列试了一下,超时..所以,能用优先队列的,就要用优先队 ...

  9. 【hibernate】<第一节>hibernate简单入门

    所需工具: ide:eclipse or myeclipse jdk:1.7 jar包:hibernate-distribution-3.6.0.Final 和对应mysql的驱动类(对应jar包如图 ...

  10. java9-8 局部内部类

    1. 局部内部类 A:可以直接访问外部类的成员 B:在局部位置,可以创建内部类对象,通过对象调用内部类方法,来使用局部内部类功能 面试题: 局部内部类访问局部变量的注意事项? A:局部内部类访问局部变 ...