function GetStringList1(): TStringList;
var
  sl: TStringList;
  i: integer;
begin
  sl := TStringList.Create;
  for i := 1 to 10 do
  begin
    sl.Add(IntToStr(i));
  end;
  Result := sl;
end;function GetStringList2(): TStringList;
var
  i: integer;
begin
  Result := TStringList.Create;
  with Result do
  for i := 1 to 10 do
  begin
    Add(IntToStr(i));
  end;
end;procedure TForm1.Button3Click(Sender: TObject);
var
  sl: TStringList;
begin
  sl := GetStringList1;
  //Memo1.Lines.Assign(sl);
  Memo1.Lines := sl;
  sl.Free;
end;问题1:
GetStringList1里面的局部变量sl在函数执行完成后怎么不会被free掉?
问题2:
Memo1.Lines.Assign(sl); Memo1.Lines := sl;这两个有什么区别?

解决方案 »

  1.   

    Assigned是把sl里面的内容增加到Memo1.lines中,而=直接就等过去了
      

  2.   

    第一个问题
    delphi从TObject中继承过来的在局部过程中都不会释放掉,类似于C中的static声明的变量
    function GetButto(): TButton;
    var
      sl: TButton;
    begin
      sl := TButton.Create(Nil);
      sl.caption := '123';
      Result := sl;
    end;
    这个也是一样
      

  3.   

    TStringList需要手动释放,不然存在内存泄露问题。
    最好不要把TStringList当做返回类型。
      

  4.   

    Assign 顾名思义 安排。就是把TStringList 对象 占用的内存直接安排给Memo1.Lines 。Memo1.Lines 同样也是TStringList 类型。问题一
    是因为你自己安排了内存给 TStringList 也就是 创建出来了。 你自己没有把他给Free掉。 系统不会帮你Free掉你创建出来的东西。
      

  5.   

    曾几何时我刚学编程的时候也会遇到这样的问题, 要解决这些疑问最好的方式还是先了解计算机的一些基础知识, 对于第一个问题, S1是不会自动释放的, 每个Create创建的对象必须手工执行free才算是释放,第2个问题, 对于Assign 是一种深拷贝,也就是完整的把另外一个list里的内容全部拷贝过来, Memo1.Lines.Assign(sl);
    这句话就如同执行了下面的东西
    Memo1.Lines.Clear;
    for i:= 0 to s1.count -1 do 
    begin
      Memo1.lines.add(s1[i])
    end;另外对于Memo1.Lines := sl在这里实际效果是一样 , 关键是你需要检查源码, 你可以看一下Memo的成员Lines的write 方法实际上是执行以下代码  
    property Lines: TStrings read FLines write SetLines;procedure TCustomMemo.SetLines(Value: TStrings);
    begin
      FLines.Assign(Value);
    end;
      

  6.   

    不要用Memo1.Lines := sl;这样会造成memo1构造时候创建的tstring引用丢失,最后无法销毁。而切楼主把Memo1.Lines指向的tstring手动销毁了,造成memo析构的时候无法free,估计会报内存错误。
      

  7.   


    不会的, 你可以查看代码, 一般情况这样的写法确实会导致人有这样的误解, 但是对于Memo对象它的Lines属性有Setter, 它不是直接替换引用, 而是调用了assign, 所以不会发生内存报错
      

  8.   

    实际上,你有这个疑问,是因为你对对象类型的变量不是很了解。
    就这你的问题简单说下。
    你程序中的sl,实际上是一个4字节的指针
    sl := GetStringList1;
    这句的意思是:在GetStringList1函数中,创建了一个TStringList对象实例(注意,这个对象本身所占据的内存是在堆中开辟的),然后将指向这个对象实例的指针返回来(也就是指向这个对象实例所占用内存的首地址),并将这个地址的值赋值给sl
    这里,sl是个局部变量,是在栈中分配的,大小是4字节(你可以sizeof(sl)看看)
    函数结束了,sl本身是被释放了,但是作为sl所指向的那个TStringList类并没有被释放,这个时候,因为没有任何一个变量保存这个TStringList对象实例的地址,因此也就造成了内存泄露。其实,你要是明白了我上面说的内容,也就不难理解
    memo1.lines := sl 
    这句是干什么了,他是将sl所指向的TStringList对象实例的首地址的值赋值给了Lines。
    这么赋值是不对的,memo1的Lines并不是TStringList类型的类,但是Lines和TStringList都是TStrings的子类。Lines在Memo1创建的时候,就已经被创建了,你这么赋值,就导致Lines指向的原来的那个对象实例丢了(注意,是丢了,不是被释放了,其所占的内存依然还在,但是没有变量指向他了,也就是说内存泄露了)。
    因此,这种赋值,只能使用
    Memo1.Lines.Assign(sl); 
      

  9.   

    哦,没注意TMemo 的 lines 还有写方法,呵呵
    看8楼的回复,memo1.lines := sl 和 Memo1.Lines.Assign(sl);  是一回事,呵呵。
    其实,搞清楚对象类型变量和对象之间的关系,其他的事情都好处理了。
      

  10.   


    兄弟手误了吧应该是Assign吧
      

  11.   

    delphi对象是在堆上分配内存,函数退出后,这块内存仍驻留在内存中,需要程序员手动释放。
    如果没有释放,不用担心,在Application退出后,这些内存空间会被操作系统回收的
    其他像GetMem(),New()等也是如此!而一些基本数据类型,结构体等,是在栈上分配内存,函数退出后,会自动释放内存的。