Fórum diferença entre var e out #343651
25/07/2007
0
a passagem de parametros out e var.
eu achava que o out deveria inicializar as variaveis com zero e não considerar o valor que está sendo passada a elas. Mas não consegui simular a diferença. Parece que o out é a mesmissima coisa que o var.
Alguem poderia me explicar qual a diferença entre passagem de parametros via var e out? o que dá pra fazer com um que não dá com outro?
Eis o meu código:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
Memo1: TMemo;
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
public
procedure Teste1(x: Integer);
procedure Teste2(var x: Integer);
procedure Teste3(out x: Integer);
procedure Teste4(x: PInteger);
end;
var
Form1: TForm1;
//testar sem inicializar para usar lixo de memoria
x1: Integer = 5;
const
INCREMENTO = 2;
implementation
{$R *.dfm}
procedure TForm1.Teste1(x: Integer);
begin
//x := 1;
ShowMessage(´Antes X1 = ´ + IntToStr(X));
x := x + INCREMENTO;
ShowMessage(´Depois X1 = ´ + IntToStr(X));
end;
procedure TForm1.Teste2(var x: Integer);
begin
//x := 1;
ShowMessage(´Antes X2 = ´ + IntToStr(X));
x := x + INCREMENTO;
ShowMessage(´Depois X2 = ´ + IntToStr(X));
end;
procedure TForm1.Teste3(out x: Integer);
begin
//x := 1;
ShowMessage(´Antes X3 = ´ + IntToStr(X));
x := x + INCREMENTO;
ShowMessage(´Depois X3 = ´ + IntToStr(X));
end;
procedure TForm1.Teste4(x: PInteger);
begin
//x^ := 1;
ShowMessage(´Antes X4 = ´ + IntToStr(X^));
x^ := x^ + INCREMENTO;
ShowMessage(´Depois X4 = ´ + IntToStr(X^));
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
//usando sempre a mesma variavel
Teste1(x1);
ShowMessage(´Externamente X1 = ´ + IntToStr(X1));
Teste2(x1);
ShowMessage(´Externamente X2 = ´ + IntToStr(X1));
Teste3(x1);
ShowMessage(´Externamente X3 = ´ + IntToStr(X1));
Teste4(@x1);
ShowMessage(´Externamente X4 = ´ + IntToStr(X1));
end;
end.valew!
Vitor Rubio
Curtir tópico
+ 0Posts
25/07/2007
Leonardobhbr
It allows a routine to return data to a variable of caller in addition to the Result value available in functions.
It is equivalent to Var except that the value should not be changed by the routine.
Delphi does not seem to enforce this, nor does it seem to enforce the need to assign a value.
Gostei + 0
25/07/2007
Vitor Rubio
só que isso só funciona para records, para variavies primitivas, como um integer, nada feito. Com objects eu não testei.
Execute esse código para você ter uma ideia do que estou falando: precisará de uma form com um memo e um button.
{
conclusão: out só se aplica somente a records
}
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TCliente = record
nome: string;
email: string;
end;
PCliente = ^TCliente;
TForm1 = class(TForm)
Memo1: TMemo;
btOk: TButton;
procedure btOkClick(Sender: TObject);
private
procedure PrintResp(resp: string);
public
procedure Teste1(x: Integer);
procedure Teste2(var x: Integer);
procedure Teste3(out x: Integer);
procedure Teste4(x: PInteger);
procedure Teste5(const x: Integer);
procedure TesteCli1(x: TCliente);
procedure TesteCli2(var x: TCliente);
procedure TesteCli3(out x: TCliente);
procedure TesteCli4(x: PCliente);
procedure TesteCli5(const x: TCliente);
end;
var
Form1: TForm1;
//testar sem inicializar para usar lixo de memoria
x1: Integer = 5;
cli1: TCliente;
const
INCREMENTO = 2;
implementation
{$R *.dfm}
procedure TForm1.Teste1(x: Integer);
begin
//x := 1;
PrintResp(´***Por Valor***´);
PrintResp(´Antes X1 = ´ + IntToStr(X));
x := x + INCREMENTO;
PrintResp(´Depois X1 = ´ + IntToStr(X));
end;
procedure TForm1.Teste2(var x: Integer);
begin
//x := 1;
PrintResp(´***Por Referência (var)***´);
PrintResp(´Antes X2 = ´ + IntToStr(X));
x := x + INCREMENTO;
PrintResp(´Depois X2 = ´ + IntToStr(X));
end;
procedure TForm1.Teste3(out x: Integer);
begin
//x := 1;
PrintResp(´***Por Referência (out)***´);
PrintResp(´Antes X3 = ´ + IntToStr(X));
x := x + INCREMENTO;
PrintResp(´Depois X3 = ´ + IntToStr(X));
end;
procedure TForm1.Teste4(x: PInteger);
begin
//x^ := 1;
PrintResp(´***Por Referência (ponteiro)***´);
PrintResp(´Antes X4 = ´ + IntToStr(X^));
x^ := x^ + INCREMENTO;
PrintResp(´Depois X4 = ´ + IntToStr(X^));
end;
procedure TForm1.Teste5(const x: Integer);
begin
PrintResp(´***Por constante***´);
//não dá pra mudar o valor de x aqui
//x := 1;
PrintResp(´Antes X5 = ´ + IntToStr(X));
//x := x + INCREMENTO;
PrintResp(´Depois X5 = ´ + IntToStr(X));
end;
procedure TForm1.btOkClick(Sender: TObject);
begin
//usando sempre a mesma variavel
Teste1(x1);
PrintResp(´Externamente X1 = ´ + IntToStr(X1));
PrintResp(´---------------------------------------´);
PrintResp(´´);
Teste2(x1);
PrintResp(´Externamente X2 = ´ + IntToStr(X1));
PrintResp(´---------------------------------------´);
PrintResp(´´);
Teste3(x1);
PrintResp(´Externamente X3 = ´ + IntToStr(X1));
PrintResp(´---------------------------------------´);
PrintResp(´´);
Teste4(@x1);
PrintResp(´Externamente X4 = ´ + IntToStr(X1));
PrintResp(´---------------------------------------´);
PrintResp(´´);
Teste5(x1);
PrintResp(´Externamente X5 = ´ + IntToStr(X1));
PrintResp(´---------------------------------------´);
PrintResp(´´);
cli1.nome := ´vitor´;
cli1.email := ´vitorrubio@uol.com.br´;
TesteCli1(Cli1);
PrintResp(´Externamente Cli1:´+#13109 + ´Nome: ´ + Cli1.nome + 13109 + ´Email: ´ + Cli1.email);
PrintResp(´---------------------------------------´);
PrintResp(´´);
TesteCli2(Cli1);
PrintResp(´Externamente Cli2:´+13109 + ´Nome: ´ + Cli1.nome + 13109 + ´Email: ´ + Cli1.email);
PrintResp(´---------------------------------------´);
PrintResp(´´);
TesteCli3(Cli1);
PrintResp(´Externamente Cli3:´+13109 + ´Nome: ´ + Cli1.nome + 13109 + ´Email: ´ + Cli1.email);
PrintResp(´---------------------------------------´);
PrintResp(´´);
TesteCli4(@Cli1);
PrintResp(´Externamente Cli4:´+#13109 + ´Nome: ´ + Cli1.nome + 13109 + ´Email: ´ + Cli1.email);
PrintResp(´---------------------------------------´);
PrintResp(´´);
TesteCli5(Cli1);
PrintResp(´Externamente Cli5:´+13109 + ´Nome: ´ + Cli1.nome + 13109 + ´Email: ´ + Cli1.email);
PrintResp(´---------------------------------------´);
PrintResp(´´);
end;
procedure TForm1.PrintResp(resp: string);
begin
Memo1.Lines.Add(resp);
end;
procedure TForm1.TesteCli1(x: TCliente);
begin
PrintResp(´***Por Valor***´);
PrintResp(´Antes Cli1:´ +13109 + ´Nome: ´ + x.nome + 13109 + ´Email: ´ + x.email);
x.nome := x.nome + ´ Rubio ´;
x.email := x.email + ´; vitorrubio@gmail.com´;
PrintResp(´Depois Cli1:´ +#13109 + ´Nome: ´ + x.nome + 13109 + ´Email: ´ + x.email);
end;
procedure TForm1.TesteCli2(var x: TCliente);
begin
PrintResp(´***Por Referência (var)***´);
PrintResp(´Antes Cli2:´ +13109 + ´Nome: ´ + x.nome + 13109 + ´Email: ´ + x.email);
x.nome := x.nome + ´ Rubio ´;
x.email := x.email + ´; vitorrubio@gmail.com´;
PrintResp(´Depois Cli2:´ +13109 + ´Nome: ´ + x.nome + 13109 + ´Email: ´ + x.email);
end;
procedure TForm1.TesteCli3(out x: TCliente);
begin
PrintResp(´***Por Referência (out)***´);
PrintResp(´Antes Cli3:´ +13109 + ´Nome: ´ + x.nome + 13109 + ´Email: ´ + x.email);
x.nome := x.nome + ´ Rubio ´;
x.email := x.email + ´; vitorrubio@gmail.com´;
PrintResp(´Depois Cli3:´ +13109 + ´Nome: ´ + x.nome + 13109 + ´Email: ´ + x.email);
end;
procedure TForm1.TesteCli4(x: PCliente);
begin
PrintResp(´***Por Referência (ponteiro)***´);
PrintResp(´Antes Cli4:´ +#13109 + ´Nome: ´ + x.nome + 13109 + ´Email: ´ + x.email);
x^.nome := x^.nome + ´ Rubio ´;
x^.email := x^.email + ´; vitorrubio@gmail.com´;
PrintResp(´Depois Cli4:´ +13109 + ´Nome: ´ + x.nome + 13109 + ´Email: ´ + x.email);
end;
procedure TForm1.TesteCli5(const x: TCliente);
begin
//não pode mudar
PrintResp(´***Por Constante***´);
PrintResp(´Antes Cli5:´ +13109 + ´Nome: ´ + x.nome + 13109 + ´Email: ´ + x.email);
//x.nome := x.nome + ´ Rubio ´;
//x.email := x.email + ´; vitorrubio@gmail.com´;
PrintResp(´Depois Cli5:´ +13109 + ´Nome: ´ + x.nome + 13109 + ´Email: ´ + x.email);
end;
end.Gostei + 0
25/07/2007
Cd.beco_df
o var - variavel de entrada
e out - variavel de sáida
outro dia precisei ter um retorno em uma variavel, no create de uma classe, mas como se sabe, um create nao é um metodo que tenha retorno, qual então o meu processo para que tenha sucesso, foi criar uma entrada Out para que retornasse o valor apos a criaçao da classe, o out funciona como o result de uma function.
vou demonstrar um simples exemplo aqui...
procedure TForm1.Processa(var V1,v2 : integer; out R :integer);
begin
R:= V1 + V2;
end
viu que OUt é o Retorno, ou variavel de saida?
Gostei + 0
25/07/2007
Vitor Rubio
seguinte, use esse seu mesmo exemplo, mas passando var no lugar e out. Você vai peceber que o resultado é o mesmo e funciona da mesma maneira.
extendi o meu exemplo e o que eu descobri:
se você passar strings ou records coom out, no inicio da procedure esses valores são inicializados como vazios, mas se você passar integers, ou records que contenham integers, os integers não vão ser inicializados com 0.
Ou seja, se o objetivo é passar parametros do tipo integer, out tem o mesmissimo efeito de var. Seria um bug?
pode testar
procedure TForm1.Processa(var V1,v2 : integer; var R :integer); begin R:= V1 + V2; end
duvido que não funcione
Gostei + 0
25/07/2007
Rjun
Gostei + 0
25/07/2007
Vitor Rubio
É que, pela teoria, parametros out deveriam ser sempre inicializados automaticamente no inicio da rotina, descartando-se o seu valor inicial, não importa a linguagem que de suporte a isso. Isso acontece no delphi com todos os tipos de dados menos com integer, que é tratado o valor inicial igual se tivesse passato com o var.
eu tenho um repositório/coleção de exemplos onde eu coloco varios exemplos comentados e com arquivo readme.txt explicando pra que serve.
Simplesmente, usando integer para fazer o programinha de soma basico e classico e assim colocar esse exemplo no meu repositorio, eu simplesmente não consegui demonstrar o que eu queria: que o var usa o valor inicial enquanto que o out descarta-o, inicializando a variavel com 0;
Valew!
Gostei + 0
Clique aqui para fazer login e interagir na Comunidade :)