比如创建一个线程有下面这样两种方式
begin TMyThread.Create; end;
var myTestThread: TMyThread; begin myTestThread:= MyThread.Create; end;
第一种方式就是创建了一个线程,这个线程去执行,但是你却没有这个线程对象的指针,所以你不能去控制它,只能任由它去执行,如果能自己结束还好,但是如果是一个循环执行的线程,那么就可能在那里永远执行下去,因为你在创建它的时候,没有记录这个线程对象的指针,所以你就没办法去控制它。其实对于线程还好,你可以设置它运行结束后自动释放资源( FreeOnTerminate:= True
),但是不管是线程类还是普通类,这样创建之后就丢失了对象实体的地址,但是它还在内存中存在,这时候就只能是内存泄露。
第二种方式就是创建了一个线程,但是你记住了这个线程对象的指针,那么你就可以在必要上的时候通过这个指针来控制它。
同理很多的类创建对象都是这样的,第一种就相当于放飞了的鸟,你再也控制不了它了,而第二种就像是你在放风筝,可是那条线一直在你的手里
我们通过指针动态分配了内存之后,需要记住这个指针(该指针指向分配的内存),比如C/C++中的
int *pi; pi =(int*) malloc(10* sizeof(int));
pi 就是用来记录分配的内存的地址。在Delphi中
var pi: PInteger; begin GetMem(p, sizeof(Integer)*10); end;
这里的pi 也是用来记录分配的内存的地址。
就像上面两种情况,如果在没有释放内存之前想要让 pi 指向新的地址,这时候一定要创建新的指针首先保存 pi的值(也就是保存这块内存的地址,比如 ptemp)
C/C++中
int* ptemp = pi;
Delphi中
var ptemp: PInteger; begin ptemp:= pi; end;
再去让 pi 去指向新的地址,这样就是为了不去丢失对这块内存的控制,这样pi 不再指向这块内存,但是可以通过新的指向这块内存的指针来释放这块内存,而不至于内存泄露,比如在C/C++和 Delphi中
C/C++中
free(ptemp);
Delphi中
FreeMem(ptemp);
因为你之所以需要分配这块内存,就是要使用这块内存来存储数据、对这里的数据进行操作、以及最终去释放这块内存
只有你记录这块内存的地址,才可以通过指针来使用这块内存,并且最终才能够释放这块内存,否则分了内存确立马丢失了这块内存的地址,一方面无法使用这块内存,另一方面无法释放内存,最终导致内存泄露。
很多东西因为要强调,所以会在博客里面专门的强调、专门写强调它的代码、总结。但是在真正的项目中,往往是将所有的这个细节的小知识组合在一起使用,这些反复强调的点都融合在项目的大量的代码中,并不会那么明显。
很多技术博客只是将真实项目中的很多具体的技术点逐个拿出来单独强调,但是在真实的项目开发中,往往是很多的各种各样的技术点混在一起,根本没有博客里面体现的那么清楚。所以这个就是很多人觉得学习某个知识点很简单,但是真到具体的开发中就感觉理不清楚的原因。
那么一方面就是先将这些具体的知识点弄清楚,然后在具体的应用(以及研究源码)、设计的时候不要将所有的知识混在一起看待---确实是要将所有需要的知识点混在一起用,而是要先逐个的明白各个知识点怎么在项目中应用,然后才能将它们结合在一起而不至于将自己弄迷糊