# 构造函数: 概念: 实例化时,用于初始化的函数 不写默认有一个无参构造函数 ==可以重载== 通常用法: 自定义初始化规则 语法: 访问修饰符 类名(){} 案例: ```Csharp class Person() { public string name; public int age; public Person() { name = "默认值"; age = 默认值; } } ``` this关键字: this指当前类声明的成员变量 ```Csharp class Person() { public string name; public int age; public Person() { name = "默认值"; age = 默认值; } public Person(int age,string name) //重构 { this.name = name; //后面的name是传递的参数,this.name是最上方public int出来的 this.age = name; } } ``` 特殊写法: 通过this重用构造函数代码,即先调用无参构造函数,然后在调用这个特殊写法的构造函数 语法:访问修饰符 构造函数名(参数列表):this(【可选】参数1,参数2.....) 例子: ```Csharp public Person(int age, string name):this(age) { balabala } ``` 过程:先调用无参Person构造函数,然后寻找只有构造单个参数age的构造函数进行初始化 注意: ==函数名和类名必须相同== ==没有特殊用途,一般都是public== ==如果写了有参构造函数且自己没有保留无参构造函数,那么类在实例化时只能使用有参构造函数且无法使用无参构造函数== ---- # 析构函数 概念: 当引用类型堆内存被回收时,会调用该函数 对于需要手动管理内存的语言(C++),需要在析构函数中做一些内存回收处理 C#有自动垃圾回收机制GC Unity中基本不用管 通常用法: 语法: ```Csharp ~类名() { } ``` 案例: ```Csharp ~Person() { } ``` 注意: ---- # 垃圾回收 垃圾回收(GC) 通过遍历堆Heap上动态分配的所有对象 通过识别他们是否被引用来确定哪些对象时垃圾,哪些对象仍然需要引用 垃圾:没有变量或对象引用的内容 如果是垃圾就要被回收释放 一般都是==被动触发(会造成卡顿)==,所以游戏一般需要手动执行垃圾回收 语法:GC.Collect(); ==GC会造成卡顿,所以在加载Loading时一般会调用== 垃圾回收有多种算法 引用计数 标记清楚 标记整理 复制集合 注意: GC只负责Heap内存的垃圾祸首 引用类型都是在Heap中的,所以他需要GC来进行管理 栈Stack上的内存时系统自动管理的 所以不需要GC C#中垃圾回收机制的大概原理 他会把内存分为0,1,2代内存 代的概念是垃圾回收中的一种算法需要 新分配的对象都会被配置在第0代内存中 每次分配都可能会进行垃圾回收(一般来说0代内存满了就会触发) 在第一次内存回收过程开始时,垃圾回收器会认为堆中全是垃圾,会进行一下两部 1.标记对象,从根(静态参数、方法参数)开始检查引用对象,标记后为可达对象,未标记就是不可大对象 不可达对象就会认为是垃圾 2.搬迁对象 压缩堆 (挂起执行内存托管代码线程:把第0代内存(还不是垃圾的内存)放到一代进行搬迁)释放未标记的对象、搬迁可达对象、修改引用地址 大对象总被认为是二带内存,目的是减少性能损耗 不会对大对象进行压缩搬迁 大对象是85000kb以上的 示意图 step1:程序放入内存 ![[Pasted image 20260412210327.png|697]] step2:发现沾满了 ![[Pasted image 20260412210704.png]] step3:原来的地址搬迁,无引用的垃圾丢掉 ![[Pasted image 20260412210810.png]] step4:D放入 ![[Pasted image 20260412210946.png]] step5:如果0代1代后续又满了,那么这套算法会同时做用在两代内存中,以此类推 类似多级缓存cache,L1最快但常换L3最慢 <<<<<<< ours #基础 ======= #基础 >>>>>>> theirs