C#重启 --- 数据类型

 

1.分为两大类:存数据的和存地址的

1.占用空间小的归类为值类型,占用空间大的归类为引用类型 

2.int , double等数值类型,bool类型和char类型的本质都是结构体

3.string类型,所有的数组类型,以及委托都是类

1.数据必须先加载到内存中,CPU才能够去处理这些数据

2.内存的作用是存储正在执行的程序和数据

1.一个程序在运行之前首先要做的就是向系统申请内存中的执行空间

2.申请到内存中的执行空间之后再通过CLR将空间进行逻辑上的划分

3.一般将申请到的内存空间划分为栈区,堆区和静态区(存储常量)

 

1.引用其实就是数据的内存地址 

1.在方法中创建值类型的变量时,这个变量的声明在栈中,且会在栈中开辟内存空间存储这个变量所对应的数据

2.在方法中创建引用类型的变量时,这个变量的声明在栈中,同时也会在栈中给这个变量开辟一个内存空间,但是这个内存空间中存储的不是变量对应的数据(这些数据会存储在堆区开辟的内存空间中),存储的是变量所对应的堆区内存空间的内存地址(32为系统中,为这个变量开辟的空间大小为4个字节,64位则为8个字节)

1.值类型变量在栈中的内存空间中存储是数据本身,引用类型变量在栈中的内存空间中存储的是内存地址,这个内存地址对应的内存空间在堆区,且存储的是变量对应的数据

2.声明变量就是在栈区中开辟空间

3.在C#中,string数据类型是引用数据类

4.每有一个字符串 / 一个字符,都需要在堆区中创建一个内存空间来进行存储,且这些存储到堆区的字符串 / 字符都是只读的,无法进行修改

5.当我们把一个数据赋值给引用类型变量的时候,我们做了两件事:

一.在堆区中开辟内存空间存储数据

二.将在堆区中开辟的内存空间的地址传给引用类型变量,使得地址存储在栈中为变量开辟的内存空间

6.引用类型变量[ 下标 ] --- 出现左边这样的组合的时候,就意味着我们对引用类型变量进行了解引用,此时我们能够得到引用类型变量存储的地址 + 下标 * 步长后得到的地址对应的内存空间中存储的数据

7.传参,传参,是在将数据传给形参

8.当我们创建了一个引用类型变量的时候

9.不同的引用变量中装的是一样的地址,通过一个引用变量操作堆区中的数据,然后再通过另一个引用变量访问堆区时就能够访问到已经操作好的数据了

计算机在进行比较的时候,比较的是内存中的数据(数据相同为true,不同为false) 

1.值参数 --- 传递实参变量在栈区中存储的内容(包括数据和内存地址)

2.引用参数 --- 传递实参变量自身的内存地址 --- 引用参数的使用前提是在对应的值参数前用关键字 ref(reference) 进行修饰,修饰后值参数就会变为引用参数了

给引用参数传参的时候我们需要在我们传递的变量的变量名前面加上关键字 ref 进行修饰(修饰的作用是让计算机判断的出我们传递的不是数据而是变量自身的内存地址)

当我们在函数中给引用参数赋值的时候,同时也会修改实参变量的值

(引用参数中存的是实参变量的内存地址,指向的是实参变量在栈中的内存空间,直接给引用参数赋对应数据的话就相当于将引用参数解引用,找到引用参数指向的内存空间,然后将要赋值数据存储到解引用后找到的内存空间中) 

1.引用参数和输出参数能够实现的效果是一样的,但是二者之间有两个区别

一:输出参数必须在函数内被赋值,而引用参数不用

二:传给输出参数的实参变量可以不初始化,而引用参数不行 

当函数内只有 return 的时候调用一次函数只能够返回一个值,如果我们想调用一次函数后让函数返回多个值的话,就需要使用输出参数了

输出参数的特点就是传过来的实参不需要初始化,其初始化是在函数内进行的

使用方法的时候打一个小括弧后停住就会自动显示这个方法的详细信息了,不要打两个小括弧加分号,这样打的话就不会出现函数的详细信息了 

PS:

给引用参数传参和给输出参数传参的时候,我们需要在传参时,在变量的变量名前分别用用 ref 和 out 进行修饰

 总结:记住三句话

数据类型分为值类型和引用类型,值类型直接存数据,引用类型存引用(地址)

内存分配:小的放栈区,大的放堆区。栈区空间小读取速度快,堆区空间大读取速度慢

占内存大的是引用类型,占内存小的是值类型

1.将在堆区中申请到的内存进行标记,如果GC能够通过引用访问到这些内存的话,这些内存就会被保留,如果无法访问到的话,这些内存就会被回收

2.当GC开始工作的时候,CPU就会将大部分的可执行时间片分给GC调用,此时其它的程序任务的运行就会出现停顿

3.GC的工作时间分为两种,一种是自动工作,另一种是我们主动申请GC工作(通过代码设定)

自动工作的时机是在内存快使用完毕的时候GC才开始工作

主动工作的时机则是我们通过代码设定的

 

拆箱操作可以理解为解引用访问堆区内存空间中的数据,装箱操作则可以理解在堆区中申请一块内存空间存储数据并将内存空间的地址进行返回

 

1.装箱操作要尽可能的避免! --- 面试的时候这么说,但是实际上该怎么用拆装箱就怎么用拆装箱,对性能的影响微乎其微

 

 关于string数据类型,需要介绍一个名为字符串池的概念

1.首先字符串类型是一个引用类型,其存储的地址是字符串在字符串池中对应的内存空间的地址(字符串池区域开辟在堆区中)

2.然后每当我们创建了一个字符串的时候,如果字符串池中没有这个字符串的话,计算机就会自动帮我们在字符串池中分配内存空间存储这个字符串的数据,如果有的话则不创建

3.当我们将一个字符串赋值给字符串类型变量的时候(假设字符串池中已经有这个字符串,如果没有则创建),字符串变量在栈区的内存空间中实际存储的是字符串在字符串池中的对应内存空间的地址

所有的字符串在创建之后都是只能进行读操作不能进行修改操作的

(需要频繁的对字符串进行增删改的时候就用StringBuilder) ,不然的话用string就可以了

 介绍一个可变字符串类型 --- StringBulider

首先这是一个引用类型,初始化这个类型的步骤是在堆区中new一个内存空间,new后这个二内存空间的内存地址就会返回给变量存储,语法如上

(注意!这个内存空间中只能够存储字符串和字符)

在new的括号里不填任何的东西的话,这个内存空间会按照默认大小进行开辟,如果我们填某个整数的话,开辟的内存空间大小就等于给定的整数 * 一个字节的大小

1.在这个内存空间中存储的字符串是可以更改的(字符串类型对应的内存空间中存储的字符串是不可更改的,字符变量可以(值类型))

2.注意这个变量不是字符串类型而是可变字符串类型,如果想要将这个变量以字符串的形式输出的话,我们需要通过可变字符串变量调用ToString方法才可以

3.当存储进可变字符串变量对应的内存空间中的数据大于内存空间自身的容量时,可变字符串类内部会自己调用方法,在堆区中新申请一块更大的内存空间,然后将数据拷贝到新的内存空间中,并将地址返回给可变字符串变量(此时原本开辟的内存空间就变为了垃圾!我们要尽可能的避免这种情况

(方法都执行在栈中,执行完毕后就会自动清除栈帧)

(值类型直接存储数据)

(引用类型直接存储引用(地址))

猜你喜欢

转载自blog.csdn.net/qq_51947882/article/details/127653701
今日推荐