在delphi中为分支声明块级变量

时间:2011-06-29 10:30:46

标签: delphi

在Delphi prism中,我们可以声明仅在特殊情况下需要的变量。

例如: 在棱镜中

 If acondition then
     begin
        var a :Integer;
     end;
    a := 3; //this line will produce error. because a will be created only when the condition is true

这里'a'不能与3分配,因为它嵌套在分支内。 我们如何声明一个只能在delphi win32中的分支内部使用的变量。所以我可以减少内存使用量,因为只有在某个条件成立时才会创建它;

如果减少内存使用量不是问题我们有什么缺点(或者我们没有)

6 个答案:

答案 0 :(得分:8)

你的问题的前提是错误的。您假设在允许块级变量的语言中,当控制进入或离开这些变量的范围时,程序会为这些变量分配和释放内存。因此,例如,您认为当acondition为真时,程序会调整堆栈,以便在a变量进入该块时腾出空间。但你错了。

编译器计算所有声明的变量和临时变量所需的最大空间,然后在进入函数时保留那么多空间。分配该空间就像调整堆栈指针一样简单;所需时间通常与预留的空间量无关。最重要的是,你的想法实际上不会节省任何空间。

拥有块级变量的真正好处是它们的范围有限。

如果您确实需要某些变量仅在一个代码分支中有效,那么请将该分支分解为单独的函数并将变量放在那里。

答案 1 :(得分:7)

Delphi不支持Java中的局部变量声明语句的概念,但您可以声明一个子过程:

procedure foo(const acondition: boolean);

  procedure subFoo;
  var
    a: integer;
  begin
    a := 3;
  end;

begin
  If acondition then
  begin
    subFoo;
  end;
end;

答案 2 :(得分:3)

Delphi中没有办法将变量的范围限制为小于整个例程。在单个整数变量的情况下,担心它是没有意义的......但是在大数据结构的情况下,你应该动态分配它,而不是静态分配,即代替

var integers: array[1..10000]of Integer;

使用

type TIntArray: array of Integer;
var integers: TIntArray;
If acondition then
 begin
    SetLength(integers, 10000);
    ...
 end;

答案 3 :(得分:3)

您可以使用(dreaded)with语句以及返回记录的函数来模拟块级变量。这是一些示例代码,用浏览器编写:

type TIntegerA = record
  A: Integer;
end;

function varAInteger: TIntegerA;
begin
  Result.A := 0;
end;

// Code using this pseudo-local-variable
if Condition then
  with varAInteger do
  begin
    A := 7; // Works.
  end
else
  begin
    A := 3; // Error, the compiler doesn't know who A is
  end;

编辑以澄清此命题

请注意,这种魔法并不能真正替代真正的块级变量:即使是那些可能在堆栈上分配的那些,就像大多数其他局部变量一样,编译器也不适合对待它们。它不会进行相同的优化:返回的记录将始终存储在实际的内存位置,而真正的本地变量可能与CPU寄存器相关联。编译器也不允许你将这些变量用于"for"语句,这是一个很大的问题。

答案 4 :(得分:3)

要注意它只能是“语法糖”。编译器可能会确保您不使用内部作用域之外的变量,但这并不意味着它可以节省内存。无论如何,无论是否实际使用,该变量都可以在过程条目代码中分配在堆栈上。 AFAIK大多数ABI在进入时初始化堆栈并在退出时清理它。在执行函数时以更复杂的方式操作堆栈(包括处理不同的执行路径)可能性能更差 - 而不是单个指令来保留堆栈空间,您需要在代码中分散多个指令,并确保堆栈已恢复正确添加更多,特别是由于异常导致的堆栈展开可能会变得更加复杂。 如果目的是编写“更好”的代码,因为更好的范围处理,以确保错误的地方没有使用错误的变量,它可能是有用的,但如果你需要它作为一种节省内存的方法,它可能不是正确的方法

答案 5 :(得分:2)

评论了所有这些 - 德尔福有一个派对技巧,它比简单的局部变量有更多的用途,可以实现你的目标:

  function Something: Integer;
  begin 
    // don't want any too long local variables...
    If acondition then
      asm
        // now I have lots of 'local' variables available in the registers 
        mov EAX, @AnotherVariable  //you can use pascal local variables too!
        // do something with the number 3
        Add EAX, 3
        mov @Result, EAX
        jmp @next
 @AnotherVariable: dd 10
 @next:
      end;
    end;
  end; 

:))一点毫无意义的例子......