zoukankan      html  css  js  c++  java
  • 不是什么时候都可以用栈来声明对象并使用(自动释放)——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的实现代码了。

  • 相关阅读:
    【Unity与Android】02-在Unity导出的Android工程中接入Google AdMob广告
    【Unity与Android】01-Unity与Android交互通信的简易实现
    Unity3D热更新之LuaFramework篇[10]--总结篇
    Unity3D热更新之LuaFramework篇[09]--资源热更新与代码热更新的具体实现
    Unity3D热更新之LuaFramework篇[08]--热更新原理及热更服务器搭建
    Unity3D热更新之LuaFramework篇[07]--怎么让unity对象绑定Lua脚本
    Unity3D热更新之LuaFramework篇[06]--Lua中是怎么实现脚本生命周期的
    Unity3D热更新之LuaFramework篇[05]--Lua脚本调用c#以及如何在Lua中使用Dotween
    Unity3D热更新之LuaFramework篇[04]--自定义UI监听方法
    Unity3d之-使用BMFont制作美术字体
  • 原文地址:https://www.cnblogs.com/findumars/p/5180880.html
Copyright © 2011-2022 走看看