哈哈,解决了: unit Unit2;interface uses classes,sysutils,windows; type TStash = class private FItemSize:Integer; FItemNum:Integer; FSize:Integer; FDataStream: Array of Pointer; public constructor create(ItemLen:Integer); destructor destroy; procedure Add(Item:Pointer); procedure Del(Index:Integer); function Get(Index:Integer):Pointer; property Count:Integer read FItemnum; end;implementation{ TStash }procedure TStash.Add(Item: Pointer); begin if FItemNum>=FSize then begin SetLength(FDataStream,FSize+10); Inc(FSize,10); end; GetMem(FDataStream[FItemNum],FItemSize); MoveMemory(FDataStream[FItemNum],Item,FItemSize); Inc(FItemNum); end;constructor TStash.create(ItemLen: Integer); begin FItemSize:=ItemLen; FItemNum:=0; FSize:=10; SetLength(FDataStream,10); end;procedure TStash.Del(Index: Integer); begin if (Index>=FItemNum) or (Index<0) then exit; System.Move(FDataStream[Index+1],FDataStream[Index], (FItemNum-Index)*FItemSize); Dec(FItemNum); end;destructor TStash.destroy; begin FItemNum:=0; FreeMem(FDataStream); inherited; end;function TStash.Get(Index: Integer): Pointer; begin if (Index>=FItemNum) or (Index<0) then exit; result:=FDataStream[Index]; end;end. ////////////////////////////// procedure TForm1.Button1Click(Sender: TObject); var i,j:integer; intStash:TStash; begin intStash:=TStash.create(sizeof(integer)); for i:=0 to 10 do intStash.Add(@i); for j:=0 to intStash.Count-1 do begin i:=Integer(intStash.Get(j)^); ListBox1.AddItem(IntToStr(i),ListBox1); end; // intStash.Del(1); for j:=0 to intStash.Count-1 do begin i:=Integer(intStash.Get(j)^); ListBox1.AddItem(IntToStr(i),ListBox1); end; end;
更正: procedure TStash.Del(Index: Integer); var i:integer; begin if (Index>=FItemNum) or (Index<0) then exit; Dec(FItemNum); for i:=Index to FItemNum-1 do CopyMemory(FDataStream[i],FDataStream[i+1],FItemSize); end;
1*sizeof(int),所以A[1]表示数组中的第二个整型值,而不是A的后一个字节的值。但我上面的程序中几个地方我想不通:
memcpy(&(DataStream[ItemNum]),Item,ItemSize);
这里是指针间的拷贝,没什么说的。
for(int i=Index;i<ItemNum;i++)
{
DataStream[i]=DataStream[i+1];
}
//这里又是怎么回事?我写的时候,全是感觉,运行也正确,可一想,不对啊,DataStream是unsigned char*而不是Stash*,DataStream[1]应该指向第
二个字节才对,而程序中指向了第二个int型值,DataStream怎么知道存在他里面的是以32字节为单位的int型呢?
劳驾帮我分析一下,感激不尽。
如:
var A: array[1..4] of Char;
B: Integer;
begin
Move(A, B, SizeOf(B)); { SizeOf = safety! }
end;其它问题我还在看
因为你是这样为它分配内存的呀
DataStream=(unsigned char*)malloc(10*sizeof(ItemSize));
而ItemSize是int,不是吗?
classes, SysUtils;type
TStash = class
private
FItemSize, FItemNum, FSize: Integer;
FDataStream: PPointerList; // PPointerList = ^TPointerList;
//TPointerList = array[0..MaxListSize - 1] of Pointer;
public
constructor Create(ItemLen: Integer);
destructor Destroy; override;
procedure Add(Item: Pointer);
procedure Del(Index: Integer);
function Get(Index: Integer): Pointer; property Count: Integer read FItemNum;
end;implementationconstructor Tstash.Create(ItemLen: Integer);
begin
FItemSize := ItemLen;
FItemNum := 0;
FSize := 0;
GetMem(FDataStream, 10 * FItemSize);
end;destructor TStash.Destroy;
begin
FItemNum := 0;
FreeMem(FDataStream);
end;procedure TStash.Add(Item: Pointer);
begin
if FItemNum >= FSize then
begin
ReallocMem(FDataStream, (FSize + 10) * FItemSize);
Inc(FSize, 10);
end;
system.Move(Item, Fdatastream^[FItemNum], FItemSize);
Inc(FItemNum);
end;procedure TStash.Del(Index: Integer);
begin
if (Index >= FItemNum) or (Index < 0) then Exit;
system.Move(FDataStream^[Index + 1], FDataStream^[Index], (FItemNum - Index) * FItemSize);
Dec(FItemNum);
end;function TStash.Get(Index: Integer): Pointer;
begin
if (Index >= FItemNum) or (Index < 0) then Exit;
Result := FDataStream^[Index];
end;end.
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, Stash;type
TForm1 = class(TForm)
Button1: TButton;
Memo1: TMemo;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private { Private declarations }
public
{ Public declarations }
end;var
Form1: TForm1;implementation{$R *.dfm}procedure TForm1.Button1Click(Sender: TObject);
var
Stash: TStash;
I: Integer;
a, b, c: Integer;
begin
Stash := TStash.Create(sizeof(Integer));
//for I := 0 to 5 do Stash.Add(@I);
//error! @I都是同一地址!!!调用Del时会出错
a := 0;
b := 1;
c := 2;
//correct! a,b,c 变量的地址都不同!
try
with Stash do
begin
Add(@a);
Add(@b);
Add(@c);
end;
Memo1.Lines.Clear;
for I := 0 to Stash.Count - 1 do
Memo1.Lines.Add(IntToStr(integer(Stash.Get(I)^))); Memo1.Lines.Add('');
Stash.Del(0);
for I := 0 to Stash.Count - 1 do
Memo1.Lines.Add(IntToStr(integer(Stash.Get(I)^)));
finally
Stash.Free;
end;
end;procedure TForm1.Button2Click(Sender: TObject);
begin
close;
end;end.
比如init中的
ItemSize=ItemLen
DataStream=(unsigned char*)malloc(10*sizeof(ItemSize));
而你调用时是intStash.Init(sizeof(int));
ItemLen已经是长度了,何必还要sizeof(ItemSize)?还有
for(i=0;i<=30;i++)
intStash.Add(&i);
c++编译器中不会每次为i重新分配地址
因此,加入的都是同一个地址
i++后,intStash中的值也会随着便,而且所有的值都会相同!!
你的运行之所以正确,是因为你仍用了同一个i做for的循环变量!
unit Unit2;interface
uses
classes,sysutils,windows;
type
TStash = class
private
FItemSize:Integer;
FItemNum:Integer;
FSize:Integer;
FDataStream: Array of Pointer;
public
constructor create(ItemLen:Integer);
destructor destroy;
procedure Add(Item:Pointer);
procedure Del(Index:Integer);
function Get(Index:Integer):Pointer;
property Count:Integer read FItemnum;
end;implementation{ TStash }procedure TStash.Add(Item: Pointer);
begin
if FItemNum>=FSize then
begin
SetLength(FDataStream,FSize+10);
Inc(FSize,10);
end;
GetMem(FDataStream[FItemNum],FItemSize);
MoveMemory(FDataStream[FItemNum],Item,FItemSize);
Inc(FItemNum);
end;constructor TStash.create(ItemLen: Integer);
begin
FItemSize:=ItemLen;
FItemNum:=0;
FSize:=10;
SetLength(FDataStream,10);
end;procedure TStash.Del(Index: Integer);
begin
if (Index>=FItemNum) or (Index<0) then
exit;
System.Move(FDataStream[Index+1],FDataStream[Index],
(FItemNum-Index)*FItemSize);
Dec(FItemNum);
end;destructor TStash.destroy;
begin
FItemNum:=0;
FreeMem(FDataStream);
inherited;
end;function TStash.Get(Index: Integer): Pointer;
begin
if (Index>=FItemNum) or (Index<0) then
exit;
result:=FDataStream[Index];
end;end.
//////////////////////////////
procedure TForm1.Button1Click(Sender: TObject);
var
i,j:integer;
intStash:TStash;
begin
intStash:=TStash.create(sizeof(integer));
for i:=0 to 10 do
intStash.Add(@i);
for j:=0 to intStash.Count-1 do
begin
i:=Integer(intStash.Get(j)^);
ListBox1.AddItem(IntToStr(i),ListBox1);
end;
//
intStash.Del(1);
for j:=0 to intStash.Count-1 do
begin
i:=Integer(intStash.Get(j)^);
ListBox1.AddItem(IntToStr(i),ListBox1);
end;
end;
procedure TStash.Del(Index: Integer);
var
i:integer;
begin
if (Index>=FItemNum) or (Index<0) then
exit;
Dec(FItemNum);
for i:=Index to FItemNum-1 do
CopyMemory(FDataStream[i],FDataStream[i+1],FItemSize);
end;