diferença entre var e out
estou tentando desenvolver um exemplo que demonstre a diferença entre
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:
valew!
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
Curtidas 0
Respostas
Leonardobhbr
25/07/2007
The Out directive identifies a function or procedure parameter as being a variable reference for outputting to only.
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.
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
Vitor Rubio
25/07/2007
tudo bem, isso está escrito no help do Delphi 7, mas, indo mais a fundo, a ideia basica por traz do out, em qualquer linguagem, é agir como se fosse o var, retornando o valor real da variavel a procedure chamadora, porem ignorando o valor inicial desta, e não usando-o como no caso de var.
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.
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
Cd.beco_df
25/07/2007
ha uma diferença enorme entre o var e out,
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?
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
Vitor Rubio
25/07/2007
essa diferença teorica eu conheço, mas na pratica, todo esse código que eu criei foi só para exemplificar, vc chegou a ver?
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
duvido que não funcione
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
Rjun
25/07/2007
E qual o problema disso?
GOSTEI 0
Vitor Rubio
25/07/2007
não é bem um problema.
É 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!
É 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