大悟还俗

邮箱 key_ok@qq.com 我的收集 http://pan.baidu.com/share/home?uk=1177427271
  新随笔  :: 联系 :: 订阅 订阅  :: 管理

【容器+结构体】

Posted on 2013-10-09 11:28  大悟还俗_2  阅读(379)  评论(0编辑  收藏  举报

【容器+结构体】注意事项1

//这里的List是一种容器,是一种泛指,可以是List、StringList、ThreadList、ObjectList等!

//现以List为例做一个例子!

unit StudentExample;

interface

uses
  Classes,SysUtils,Dialogs;

type
  //定义结构体及其指针,定义指针目的在于把指针放到List容器中
  PStudent = ^TStudent;
  TStudent = packed record
    Name: PChar;//这里以指针数据为例(简单数据类型太简单,没什么可注意的)
    Age: Integer;
  end;

  TStudentExample=class
  private

    FStudentList:TList ;//容器List
    procedure ClearStuInfo;
  public
    constructor Create;
    destructor  destroy;override;
    procedure AddStuInfo;//生成结构体,并把指针添加信息至List
    procedure DisplayStuInfo;//显示List内结构体

  end;
implementation

constructor TStudentExample.Create;
begin
  inherited;
  FStudentList:=TList.Create;
end;

destructor  TStudentExample.destroy;
begin
  ClearStuInfo;
  FStudentList.free;
  inherited;
end;

procedure TStudentExample.AddStuInfo;
var
  PStu:PStudent;
  FIndex:Integer;
begin
  for FIndex:=0 to 3 do
  begin
     New(PStu);
     GetMem(PStu^.Name,10);//对结构体内的PChar指针进行分配内存
      StrPCopy(PStu^.Name,'Lp'+IntToStr(FIndex));
     PStu^.Age:=FIndex;
     FStudentList.Add(PStu);
  end;
end;

procedure TStudentExample.ClearStuInfo;
var
  FIndex:Integer;
begin
   for FIndex:=0 to 3 do
   begin
    //注意1:
     //用GetMem进行申请的内存须用FreeMem来释放!
     //如果不释放这里会出现内存泄露
     FreeMem(PStudent(FStudentList.Items[FIndex]).Name);
    //注意2:
     //用New申请的内存须用Dispose来释放
     Dispose(PStudent(FStudentList.Items[FIndex]));
   end;

end;

procedure TStudentExample.DisplayStuInfo;
var
  FIndex:Integer;
begin
  for FIndex:=0 to 3 do
  begin
     ShowMessage('name='+PStudent(FStudentList.Items[FIndex]).Name);
     ShowMessage('age='+Inttostr(PStudent(FStudentList.Items[FIndex]).age)) ;
  end;
end;

end.
 
View Code

 

 

 

【容器+结构体】注意事项2

 

用无类型指针释放

 

 

unit Unit2;

interface

uses
  Classes,SysUtils,Dialogs;

type
  PStudent = ^TStudent;
  TStudent = packed record
    Name: String;//这里以String为例,众所周知,String为一个指针,不用GetMem来显式申请内存,并且其内有计数,由RTL来管理生命周期
     Age: Integer;
  end;

  TStudentExample=class
  private

    FStudentList:TList ;
    procedure ClearStuInfo;
  public
    constructor Create;
    destructor  destroy;override;
    procedure AddStuInfo;
    procedure DisplayStuInfo;

  end;
implementation

constructor TStudentExample.Create;
begin
  inherited;
  FStudentList:=TList.Create;
end;

destructor  TStudentExample.destroy;
begin
  ClearStuInfo;
  FStudentList.free;
  inherited;
end;

procedure TStudentExample.AddStuInfo;
var
  PStu:PStudent;
  FIndex:Integer;
begin
  for FIndex:=0 to 3 do
  begin
     New(PStu);
     PStu^.Name:='lp'+Inttostr(FIndex);
     PStu^.Age:=FIndex;
     FStudentList.Add(PStu);
  end;
end;

procedure TStudentExample.ClearStuInfo;
var
  FIndex:Integer;
begin
   for FIndex:=0 to 3 do
   begin
     //Dispose(FStudentList.Items[FIndex]);
     //这时如果用无类型指针释放FStudentList内的结构体时,不能对其内的String进行释放,也就是无法对String进行引用减1,从而导致在释放结构体时释放不完整!下面的代码是正确的!对于为什么会这样,大家看一下__Finalize(p, typeinfo)的VCL代码
     Dispose(PStudent(FStudentList.Items[FIndex]));
   end;

end;

procedure TStudentExample.DisplayStuInfo;
var
  FIndex:Integer;
begin
  for FIndex:=0 to 3 do
  begin
     ShowMessage('name='+PStudent(FStudentList.Items[FIndex]).Name);
     ShowMessage('age='+Inttostr(PStudent(FStudentList.Items[FIndex]).age)) ;
  end;
end;

end.
View Code