简单到不能再简单的问题---大家来抢分啊(50分)

  • 主题发起人 主题发起人 xiao.lit
  • 开始时间 开始时间
X

xiao.lit

Unregistered / Unconfirmed
GUEST, unregistred user!
各位前辈,近日小弟在写一个弱智程序时作了以下的定义:

type
pMyLinkListElem=MyLinkListElem^;
MyLinkListElem=class
Prev,Next:pMyLinkListElem;
public
Constructor Create;
end;

MyLinkList=class
Head:pMyLinkListElem;
public
Constructor Create;
procedure Add(p:pMyLinkListElem);//将节点插入链表
end;


.........
然后在实现部分有:
Constructor MyLinkListElem.Create;
begin
prev := NiL;
next := NiL;
end;


在程序中调用时:
var
p:pMyLinkListElem;
L:MyLinkList;
begin
new(p);

//设置各个成员的属性
L.Add(p);
end;

当调用到 new(p) 后,在 MyLinkListelem.Create 中发生错误
但如果把 class 改为 object 一切 OK
为什么?
 
[Error] Unit1.pas(10): Undeclared identifier: 'MyLinkListElem'
????
 
是否在Create函数中加上:

inherited Create;

 
还是不行
 
应先进行如下操作:
L:=MyLinkListElem.Create;
 
过去用PASCAL的OBJECT就知道 它不用调用CREATE
若用CLASS就要调用CREATE
 
Delphi中所有的类都是由TObject的,创建新的对象必须调用Create方法。
 
to njdxzjj:
L 是MyLinkList对象而不是MyLinkListElem对象
to clyin:
如果我是这样
var
elem:MyLinkListElem;
begin
elem := MyLinkListElem.Create;
end;
的话当然没问题,但是我是动态的构造节点并把它插入链表,我能这样用吗?
new(p);
p := MyLinkListElem.Create;
就是我构造出来的对象能够赋值给一个指针吗?


各位过路的大虾也帮忙看看,都是些基础知识来的
 
我看用new(p)的话是会有问题的。
我怕出问题又拿了你的代码试了一下,new(p)根本就不会去执行mylinlistelem.create.
如果是c++用new是没问题的,可能delphi要显示调用create.
先用 e := MyLinkListElem.Create;再把e的地址给p行不?
 
to sonie:
应该不行.因为当那个过程一结束,局部变量e就不存在,指针就会指向一个未
定义的内存单元,会出错的
 
1.
pMyLinkListElem=MyLinkListElem^;
书写是错误的(应该是 pMyLinkListElem=^MyLinkListElem),本身是多余的!。
因为Delphi中对的所有对象(TClass 的 Instance)的引用都是指向对象的指针而不是对
象实体,也就是说 MyObj=TMyClass.Create(...) 之后 MyObj 本来就是指针,直接加入链
表即可(L.Add(TMyClass.Create(...))),没有必要另外定义指针。
2.
New(P)后,再 P:=AnotherPointer 本身就是错误的!因为这样一来,New(P)刚建立的指
针被丢失而被AnotherPointer所取代,以后再Dispose(P)也会出错(如果这里不出错,释放
AnotherPointer时就一定出错,因为它们是同一个东东)。
如果一定要这么做,那应该 P^:=AnotherPointer;(看起来差异并不大,只是概念问题)
 
同意->龙丹^_^
 
1.
>>pMyLinkListElem=MyLinkListElem^;书写是错误的(应该是 pMyLinkListElem=^MyLinkListElem),
同意
>> 本身是多余的!。
为什么?
>>因为Delphi中对的所有对象(TClass 的 Instance)的引用都是指向对象的指针而不是对
>>象实体,也就是说 MyObj=TMyClass.Create(...) 之后 MyObj 本来就是指针,直接加入链
>>表即可(L.Add(TMyClass.Create(...))),没有必要另外定义指针。
按照你的说法,以下语句会造成内存泄漏:
var
obj1,obj2:TMyobj;
begin
obj1 := TMyObj.Create;
obj2 := TMyobj.Create;

obj1 := obj2
//obj1 原来指向的内存区域会丢失?
end;
2.
>>New(P)后,再 P:=AnotherPointer 本身就是错误的!

我想说明,在C++里面,这样的做法并不会出错,只是原来 p 指向的内存区域无法释放的结果
我想,在delphi 里面应该也是一样的吧

>>因为这样一来,New(P)刚建立的指针被丢失而被AnotherPointer所取代,
>>以后再Dispose(P)也会出错(如果这里不出错,释放
>>AnotherPointer时就一定出错,因为它们是同一个东东)。

这很显然的,同一块内存不能被释放两次

>> 如果一定要这么做,那应该 P^:=AnotherPointer;(看起来差异并不大,只是概念问题)

这是正确的(对象之间的相互赋值),但我要的是保留原来的值(将 p 插入链表)然后将 p 指
向新的内存空间,我想这应该不成问题的吧.
在这里我要的是不断将 new(p) 得到的对象插入链表,在 C++ 里应当是这样:
do{
p = new MyLinkListElem;
L.Add(p);
...
}while(!finish);

所有的内存空间在 L 析构时释放.
在 C++ 里,这是理所当然的事啊,为什么一到 delphi 里就完全变了一个样了呢?
 
1, pascal 中有两种指针的声明方法, 用途不同,
(1) pMyType = ^MyType;
MyType = record
a: Integer;
next: pMyType;
end;
(2) MyType = record
a: Integer;
b: String;
end;
pMyType = MyType^;
第一种解决了递归的问题,
第二种是通常写法,
(也许两个 ^ 位置相反, 忘了, 没法测试)
你的写法会造成泄露。
2, 一样。
没有问题,
while(condition) do
begin
new(p);
aList.add(p);
//p := aClass.create;
//aList.add(p);
// 都不会出错。
end;
通过 aList 方法来释放所有的空间。不会自动释放。
你原来的错误在于 *类本来就是指针*.
 
搞定.谢谢 superMMX 和 龙丹
将代码改为
new(p);
p^ := MyLinkListElem.Create;
L.Add(p);
就通过了.
原来如此.
但是,以下代码怎么会造成内存泄漏呢?这个问题一搞定,立马分分
var
obj1,obj2:TMyobj;
begin
obj1 := TMyObj.Create;
obj2 := TMyobj.Create;

obj1 := obj2

end;
 
关于^是的写法是错的,我也是把^提到前面调试的.
最后提出的问题
obj1:=tmyobj.create;
obj2:=tmyobj.create;
创建了两个实体,即用c的说法就是为obj1,obj2均分配了空间(都new了).
当执行了obj1:=obj2后,把obj1指向了obj2,原来的obj1的地址无法访问到了.
可把代码改成
var
obj1,obj2:tmyobj;
begin
obj2:=tmyobj.create;
obj1:=obj2;
end;

var//如你真的是要new两个object;
obj1,obj2,tempobj:tmyobj;
begin
obj1:=tmyobject.create;
obj2:=tmyocject.creat;
tempobj:=obj1;//使得原obj1可访问
obj1:=obj2;
end;
试试.
 
to SuperMMX:
p := aClass.create;
要写成 p^ := aClass.Create
才正确

to sonie:
照你那样子说法,我对自己声明的每一个对象都要手工的 Destroy 它了,那岂不要累死
例如:
var
K1 ...... Kn:TInteger
//声明 n 个对象
begin
K1 := TInteger.Create;
.....// 创建 n 个对象
......//do something
K1.Destroy;
......// 析构 n 个对象
end;
但我看都不是这样子吧,我觉得应该是在过程结束时自动析构才合理.如果是
new 出来的才要手工的释放内存
 
看来是没有办法,只能手工析购
 
接受答案了
 
后退
顶部