自己用做记录相关知识点,若你看到,则以批判眼光看,怕有些地方没说对,或有些概念不合理,误导你
关于堆区和栈区(堆栈区)
c#中垃圾回收
c#中关于堆区和栈区
参考链接如上
首先我们看看c中的一段代码
```
//main.cpp
int a = 0; //全局初始化区
int a = 0; //全局初始化区
char *p1; //全局未初始化区
main() {
int b; //栈
char s[] = "abc"; //栈
char *p2; //栈
char *p3 = "123456"; //123456\0在常量区,p3在栈上。
static int c = 0; //全局(静态)初始化区
p1 = (char *)malloc(10);
p2 = (char *)malloc(20);
//分配得来得10和20字节的区域就在堆区。
strcpy(p1, "123456"); //123456\0放在常量区,编译器可能会将它与p3所指向的"123456"优化成一个地方。
}
part1 看看c++中对象怎么分配/怎么析构的
文字说明:
c++中每个类都有构造函数和析构函数
对于栈中的对象,则不需要在析构函数中进行手动delete
操作
对于堆中的对象,则需要在析构函数中进行手动delete
操作
对于c++一些语法好久不接触所以在这里就不写相关代码
下面写c#一些代码来说明c#中对象相关
using System;
using System.Collections.Generic;
using System.Dynamic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Security.Cryptography.X509Certificates;
using System.Text;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
Test test = new Test();
//test是一个引用类型的变量(存放在栈中)
//new Test()是一个对象即实例(存放在堆中)
int x = 1;
//x是一个值类型的变量(存放在栈中)
}
}
class Test
{
public string Name { get; set; }
//这个属性里面的字段即类成员变量也在堆中
}
在c#中,引用类型变量指向的内存区域是处于堆中的实例
我们知道c++如果new个在堆中的内存,如果程序员自己不把它`detele的话,则这段内存一直被占据,没有被释放,则会导致内存泄漏。
而在c#中,我们并没有看到相关的delete操作
那是因为c#中准确的说应该是.net中比较厉害的机制了,垃圾回收机制
具体概念和内容需要找资料细看
这里大概说明下:
c#中的对象new Test()
它是放在托管队中的,而托管堆是由CLR(公共语言运行库(Common Language Runtime))管理,当堆中满了之后,会自动清理堆中的垃圾。所以,做为.net开发,我们不需要关心内存释放的问题。
那么,这个垃圾回收时怎么进行的呢,垃圾回收大概时间是在什么时候呢?
垃圾回收是在相关算法中进行(具体我也不知道…),我们是无法知道具体什么时候被回收的,不过有个范围则是
在这个堆中的对象最后一个被引用—到---程序关闭时,不同于c++,它是一种不确定回收。
所以,对于程序员而言,可以吧精力放在程序特性中,而可以放心的交给.NET进行内存管理。
回到C#中的对象引用相关操作:
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
Test test1 = new Test();
test1.Name = "jay";
Test test2 = test1;//new Test()现在被test2来引用
string name = test2.Name;
test2.Name = "jj";
Console.WriteLine(name + ' ' + test2.Name);//JAY jj
}
}
class Test
{
public string Name { get; set; }
//这个属性里面的字段即类成员变量也在堆中
}
}
int _tmain(int argc, _TCHAR* argv[])
{
int a;
int &b = a;//引用变量b指向a内存;
int &c =b;//换成引用变量c指向a内存;
}
在c++中 ,引用更接近const指针,必须在创建时进行初始化,一旦与某个变量关联起来,将一直效忠于它
上面是c++中对应一些引用程序和add watch
c++称引用只是给原先变量起了别名,这个引用的值是原来变量的值,这个引用的地址时原来变量的地址。
然后在c#中,有ref和out 引用参数和输出参数,也是变量别名
来看看c++中
我们发现在程序整个运行中a、b、c1
都是一个地址。c1值改变,则其他都改变,他们都是一个地址上的值,只是起了其他的名字
下面看看c#中关于ref和out
上面两个图说明,ref int c1,out int c2
c1
和c2
的地址和原来变量的a
和b
时一样的!在c1
和c2
上进行操作则直接影响a
和b
!
但是啊,这个ref
和out
还是些细节要说的
我们可以看到在函数调用前,a被初始化,b没有
ref需要先进行初始化,因为目调用函数需要首先对其进行读,然后你想写就写
而out是为了进行写,而不用来读取,但是out的话,在函数结束时,不能未写就出栈,一定要写。
编译器检测并提示,帮你改正
对于c#中引用类型 个人感觉相当于c++中的指针,即 Test test1 = new Test();
这里偏向指针的感觉。即这里的test1这个变量里面存放一个地址,这个地址是托管堆(可以自动进行垃圾回收)中的实例对象的存放地址
上述可能不太准确,因为这里涉及到托管,好像叫托管指针