Delphi的指针为什么可以多次New

  今天在使用Delphi的队列的时候,需要在每次将一个record压入队列的时候对该record进行New操作(分配内存空间),然后将该指针压入到队列,大概 的代码如下

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, OrderList,
  Contnrs{虽然本单元中引入了OrderList,而OrderList里面引入了Contnrs,但是还是需要再引入一次};

type
  TForm1 = class(TForm)
    edt1: TEdit;
    lbl1: TLabel;
    btn1: TButton;
    btn2: TButton;
    lbl2: TLabel;
    edt2: TEdit;
    procedure btn1Click(Sender: TObject);
    procedure btn2Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

  PStudent = ^TStudent;
  TStudent = record
    name: string;
    age: Integer;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}
var
  queue: TQueue;

procedure TForm1.btn1Click(Sender: TObject);
var
  student: PStudent;
begin
  New(student);
  student.name:= edt1.Text;
  student.age:= StrToInt(edt2.Text);

  try
    queue.Push(student);
  except
    on e: Exception do
    begin
      ShowMessage(e.Message);
    end;
  end;
end;

procedure TForm1.btn2Click(Sender: TObject);
var
  student: PStudent;
begin
  if queue.Count > 0 then
  begin
    New(student);
    student:= queue.Pop;

    Application.MessageBox(PChar(student.name+‘--‘+IntToStr(student.age)), ‘OK‘, MB_OK);
  end
  else
  //在这里加个判断队列是不是为空,就不会导致为空时出现异常
  begin
    Application.MessageBox(‘队列已经空了‘, ‘OK?‘, MB_OKCANCEL);
  end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  queue:= TQueue.Create;  //之前没有Create queue就直接进行Push,必然会出错
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  queue.Free;
end;

end.

  主要是其中 TForm1.btn1Click(Sender: TObject) 方法中关于New一个指针以及将该指针Push进入队列的相关代码,假设出现这样的情况:我多次点击按钮,那是不是会多次对一个指针进行New,另外为什么不需要进行Dispose呢?  

  到底Push进入队列是一个什么样的原理呢?

  我猜想是一个指针可以New多次,如果对一个指针进行New之后,将会在内存中分配一个空间,如果不进行Dispose,也不保存该指针的值(也就是该指针指向的位置),再次进行New的话,将会重新在内存中分配一块空间,但是之前分配的那块空间会因为地址丢失(主要是因为在New之后,原来的指针将会指向新分配的内存)而造成内存的泄露。

  所以是可以对一个指针多次New的,但是最好在每次New的时候,保存之前一次New的指针(或者继续使用其内容并在用完之后Dispose,或者直接Dispose),不要造成内存泄露。

  于是我就开始设计一个简单的程序验证我得猜想

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    btn1: TButton;
    procedure btn1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

  PStudent = ^TStudent;
  TStudent = record
    name: string;
    age: Integer;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.btn1Click(Sender: TObject);
var
  student: PStudent;
  st1: PStudent;
  st2: PStudent;
begin
  New(student);  //使用New分配内存空间,并且student指针指向该内存空间
  student.name:= ‘st1‘;  //通过指针student对该内存空间的结构体进行赋值操作
  student.age:= 10;

  st1:= student;  //使用新的指针来指向student所指向的内存空间,保存原来内存空间的地址

  New(student);  //再次New来分配空间,这时候student会指向新的内存空间,而因为之前进行了 st1:= student; 的操作,所以使用st1保存了原来的地址,而不会造成内存的丢失
  student.name:= ‘st2‘;  //通过指针student 对新内存中的结构体赋值
  student.age:= 20;

  st2:= student;  //再用st2 指针来保存新的内存地址

  ShowMessage(st1.name + ‘与‘ + st2.name);

  Dispose(st1);  //使用完成后,使用Dispose(st1); 来释放原来的内存空间
  Dispose(st2);  //其实此时Dispose(st2) 等价与 Dispose(student) 因为没有在上面进行 st2:= student 之后再次对student 进行New,所以st2与student指针都指向一个内存地址

end;

end.

  注意其中的 TForm1.btn1Click(Sender: TObject) 方法:

1. 先对一个student 指针进行New,于是就在内存中分配了一个内存空间,并且student 指针指向这块内存

2. 然后对该结构体进行赋值(就是代码中的对它的name、age赋值),然后将该指针赋给 st1指针,这个时候student 和st1 指针都同时指向了之前分配的内存空间

3. 然后在对 student指针进行New,这个时候重新分配了内存,而student 将指向该内存空间,不再指向之前的那块内存空间

   第二次对student 进行New操作,不是将student之前指向的内存清空,而是重新分配一块内存,并且使student指针不再指向原来的内存,而是指向新分配的内存

   注意因为之前已经用 st1指向原来的内尺寸空间,所以之前分配的内存空间并没有丢失,虽然不能通过student 访问和操作原来的内存(因为这时候重新用New 分配了新空间,并且student指向了新的空间),但是因为用st1 指向了这块空间,所以不会造成内存泄露,这样就可以在使用好原来的内存中的数据之后,通过st1 指针来释放内存空间。

4. 再对student指针指向的新的结构体赋值(在新分配的内存中的操作),同样为了防止再次对student 进行New,所以使用另一个指针st2 来保存这次的内存地址,保证以后可以操作以及Dispose,而不会造成内存泄露

5. 最后使用完之后,通过st1、st2来对之前的内存进行释放(使用Dispose)

时间: 2024-11-12 11:32:22

Delphi的指针为什么可以多次New的相关文章

delphi中指针操作符^的使用

To see how pointers work, look at the following example.1    var2      X, Y: Integer;   // X and Y are Integer variables3      P: ^Integer;     // P points to an Integer4    begin5      X := 17;         // assign a value to X6      P := @X;         /

Delphi函数指针的两种定义(对象方法存在一个隐藏参数self,所以不能相互赋值)

delphi中经常见到以下两种定义 Type TMouseProc = procedure (X,Y:integer); TMouseEvent = procedure (X,Y:integer) of Object; 两者样子差不多但实际意义却不一样, TMouseProc只是单一的函数指针类型; TMouseEvent是对象的函数指针,也就是对象/类的函数/方法 区别在于类方法存在一个隐藏参数self,也就是说两者形参不一样,所以不能相互转换 这也就是为什么delphi中可以这样赋值 but

Delphi 函数指针(三大好处:灵活,委托的本质,回调机制)

首先学习: 指向非对象(一般的)函数/过程的函数指针 Pascal 中的过程类型与C语言中的函数指针相似,为了统一说法,以下称函数指针.函数指针的声明只需要参数列表:如果是函数,再加个返回值.例如声明一个过程类型,该类型带一个通过引用传递的整型参数: type   IntProc = procedure (var Num: Integer); 这个过程类型与任何参数完全相同的例程兼容,即用它声明的变量,可以指向任何此类函数,并通过其进行函数的调用.下面是一个兼容例程: procedure Dou

Delphi函数指针的使用(转)

delphi中可以通过函数指针把一个函数作为参数来传递,然后在另外一个函数中调用. 1) 首先,申明函数指针类型TFunctionParameter. type          TFunctionParameter = function(const value : integer) : string; 2) 定义准备被作为参数传递的函数 function One(const value : integer) : string;         begin            result :

Delphi的指针(有图,很清楚)

Pointers are like jumps, leading wildly from one part of the data structure to another. Their introduction into high-level languages has been a step backwards from which we may never recover. — Anthony Hoare 对指针可能有最让人误解和惧怕的数据类型,因此很多程序员喜欢躲避他们. 但是指针很重要

delphi pchar 指针错误

2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 var P: Pchar; //P 是指针 CSize: Cardinal; begin CSize := MAX_COMPUTERNAME_LENGTH + 1; GetMem(P, CSIze);//在这里你给 P 分配了一块内存. P := '4321'; //这里你将 P 指向另一处含有常量 '4321' 的内存.此时先前给 P 分配的内存 //已经成了“孤岛”,就是

DELPHI指针的使用

DELPHI指针的使用 大家都认为,C语言之所以强大,以及其自由性,很大部分体现在其灵活的指针运用上.因此,说指针是C语言的灵魂,一点都不为过.同时,这种说法也让很多人产生误解,似乎只有C语言的指针才能算指针.Basic不支持指针,在此不论.其实,Pascal语言本身也是支持指针的.从最初的Pascal发展至今的Object Pascal,可以说在指针运用上,丝毫不会逊色于C语言的指针. 以下内容分为八部分,分别是 一.类型指针的定义 二.无类型指针的定义 三.指针的解除引用 四.取地址(指针赋

Delphi指针运用理解

现在是面向对象漫天飞的年代了,大家都在在谈面向对象编程.Java对指针“避而不谈”,C#虽然支持指针运用,但是也淡化处理. 然而,指针还是好完全掌握为妙,省得在开发过程碰钉子,至于对指针的运用在于开发人员的存乎于心,运用得当.指针运用的不好,不要怪开发语言及其机制.下面谈到的是在Delphi中指针的运用,至于其他语言,指针的思想是相通的. 指针是一种数据类型,和编程语言中其它的类型一样,是一种类型的区分,比如 Integer 是带符号的整型,在32位X86机中,是用4个字节表示,而指针也是用4个

终于懂了:Delphi的函数名不是地址,取地址必须遵守Object Pascal的语法(Delphi和C的类比:指针、字符串、函数指针、内存分配等)good

这点是与C语言不一样的地方,以前我一直都没有明白这一点,所以总是不明白:函数地址再取地址算怎么回事? ---------------------------------------------------------------------------------------------------------------- 在学习Delphi的时候,一个很好的建议是和C/C++去类比着学习,从指针,到内存管理,到数组,到面向对象……各个方面,都是有很多可以相似和或者也有不同的方,类比着学习,一