不是什么时候都可以用栈来声明对象并使用(自动释放)——Delphi里到处都是编译器魔法,并且自动帮助实例化界面元素指针

一直都喜欢这样显示窗口,因为简单高效:

void MainWidget::ShowMyWindow()
{
    MyWidget form(this);
    form.resize(760,611);
    form.exec();
}

今天忽然想到一个问题,栈的空间只有1M或者2M,一个窗口如果数据比较多的话,就装不下,这时候就不能使用栈来声明、使用和销毁对象了。所以就要这样写:

void MainWidget::ShowMyWindow()
{
    MyWidget* form;
    form = new MyWidget(this);
    form->resize(760,611);
    form->exec();
    delete form;
}

因为好奇,所以动手实测了一下:

void MainWidget::ShowMyWindow()
{
    Util::ShowMessage(sizeof(MyWidget));
}

这个窗口也就112字节,离1024还比较远。但那也是因为所有界面元素都是动态生成的,所有界面元素在.h文件里全部都是指针声明。否则的话,那也是不行的。

后来又测试了主窗口MainWidget,也就160,看来是够用了。

但是我特别注意到,像QSharedMemory这样真正用来记录数据的东西,不应该在栈上建立实例,否则很可能会堆栈溢出。

------------------------------------------------------------------------

题外话,Delphi窗体里虽然有众多的界面元素,但通过编译器魔法,其实也都是指针而已。当TForm.Create(self)的时候,实际上VCL帮你把所有界面元素从dfm文件中读出数据,然后自动初始化(生成实例)了:

procedure TForm1.Button1Click(Sender: TObject);
begin
        FrmFinance:=TFrmFinance.Create(self);
        with FrmFinance do
        try
          InitForm(strNumero);
          ShowModal;
        finally
          Free;
        end;
end;

这么重要的思想到今天才认识到,感觉有点失败。。。Delphi程序员们真是温室里的花朵(我是其中一朵),生在福中而不至福啊!!

为了证实这一点,现在做个小实验,新建一个项目,上面只放一个按钮Button1,然后输入以下代码:

procedure TForm1.Button1Click(Sender: TObject);
begin
  ShowMessage(IntToStr(sizeof(TForm1)));
  ShowMessage(IntToStr(sizeof(TButton)));
  ShowMessage(IntToStr(sizeof(self)));
end;

结果这三个值都是4,这其实是三个指针的长度值,真是活生生领略了Delphi的“编译器魔法”,C++就不这样,sizeof可以直接评估类所占用的内存大小。

不过没关系,Delphi也有自己的过墙梯:

procedure TForm1.Button1Click(Sender: TObject);
var
  myform : TForm;
begin
  myform := TForm.Create(self);
  ShowMessage(IntToStr(myform.InstanceSize)); // 760
  ShowMessage(IntToStr(button1.InstanceSize)); // 536
  ShowMessage(IntToStr(self.InstanceSize)); // 764
end;

结果发现,三个值分别是760、536和764。这里特别注意第三个值,是myform的内存长度(760)+Button1指针的内存长度(4),而不是myform(760)+Button1实例的长度(536)。如果再增加一个TMemo,那么form1的长度就差成了760+2*4=768,实测无误。

既然如此,请问这个Button1是什么时候实例化对象的呢?答案就是读取dfm的时候,具体哪一句语句?我估计是这句:

implementation

{$R *.dfm}

其实这还不是一句编程的语句,所以什么内容都看不到,只能等有时间研究Lazarus的实现代码了。

posted @ 2016-02-04 05:36  findumars  Views(358)  Comments(0Edit  收藏  举报