Recent

Author Topic: (SOLVED) Pass by reference  (Read 16023 times)

Jell0wed

  • New Member
  • *
  • Posts: 28
  • I love cookies.
(SOLVED) Pass by reference
« on: June 21, 2011, 09:13:42 pm »
I'm passing an argument to a function kinda like that :
Code: [Select]
function doSomething(argv : TReport);
And at the end of my function, i'm adding a log to my TReport object like that :

Code: [Select]
log := TLog.Create('Testing');
argv.AddLog(log)

I would like that the log that i'm adding stays on the object argv which is in the vars of the caller (my main function that calls doSomething(argv))

So is it possible to pass the argv by reference in Lazarus ? So when I'll do the modification, It'll be affecting the object itself and not the copy that the function does automatically?

Thanks guys!
« Last Edit: June 21, 2011, 09:48:17 pm by Jell0wed »

Jell0wed

  • New Member
  • *
  • Posts: 28
  • I love cookies.
Re: Pass by reference
« Reply #1 on: June 21, 2011, 09:47:58 pm »
I solved my own problem!
It seems to pass the objects by reference automatically! So it works!

Thanks anyway! :)

garlar27

  • Hero Member
  • *****
  • Posts: 652
Re: (SOLVED) Pass by reference
« Reply #2 on: June 21, 2011, 11:00:59 pm »
I solved my own problem!
It seems to pass the objects by reference automatically! So it works!


No, it doesn't. It works for other reasons. Try the following and you'll see:
Code: Pascal  [Select][+][-]
  1. function doSomething(argv : TReport);
  2. begin
  3.    // do some action...
  4.    argv := nil;
  5. end;
  6. var
  7.    MyArgv : TReport
  8. begin
  9.    MyArgv := TReport.Create;// or what ever the code is...
  10.    doSomething(MyArgv);
  11.    if Assigned (MyArgv) then begin
  12.       // The variable hasn't changed!!!
  13.       end
  14.    else begin
  15.       // The Variable has changed!!
  16.    end;
  17. end.
  18.  

There are a few kind of prameters: Value parameters (like the one used in "doSomething" function), Variable parameter, Out (Output) parameter, Constant parameter:
Code: Pascal  [Select][+][-]
  1. function doSomething(argv : TReport); // Value Parameter: When parameters are declared as value parameters, the procedure gets a copy of the parameters
  2. that the calling statement passes. Any modifications to these parameters are purely local to the
  3. procedure’s block, and do not propagate back to the calling block. -Copied from ref.pdf-}
  4. begin
  5. end;
  6.  
  7. function doSomething(var argv : TReport); { Variable Parameter: When parameters are declared as variable parameters, the procedure or function accesses immediatly
  8. the variable that the calling block passed in its parameter list. The procedure gets a pointer to the
  9. variable that was passed, and uses this pointer to access the variable’s value. From this, it follows that
  10. any changes made to the parameter, will propagate back to the calling block. This mechanism can be
  11. used to pass values back in procedures. Because of this, the calling block must pass a parameter of
  12. exactly the same type as the declared parameter’s type. If it does not, the compiler will generate an
  13. error. -Copied from ref.pdf-}
  14. begin
  15. end;
  16.  
  17. function doSomething(out argv : TReport); { Out Parameter: The purpose of an out parameter is to pass values back to the calling routine: the variable is passed
  18. by reference. The initial value of the parameter on function entry is discarded, and should not be
  19. used.
  20. If a variable must be used to pass a value to a function and retrieve data from the function, then a
  21. variable parameter must be used. If only a value must be retrieved, a out parameter can be used. -Copied from ref.pdf-}
  22. begin
  23. end;
  24.  
  25. function doSomething(const argv : TReport); // Constant Parameter
  26. begin
  27. end;
  28.  

Download documentation from here.
Or look here for more help.

Zoran

  • Hero Member
  • *****
  • Posts: 1988
    • http://wiki.lazarus.freepascal.org/User:Zoran
Re: (SOLVED) Pass by reference
« Reply #3 on: June 21, 2011, 11:22:35 pm »
Look here to learn about parameter types: http://www.freepascal.org/docs-html/ref/refse59.html
Swan, ZX Spectrum emulator https://github.com/zoran-vucenovic/swan

Jell0wed

  • New Member
  • *
  • Posts: 28
  • I love cookies.
Re: (SOLVED) Pass by reference
« Reply #4 on: June 22, 2011, 07:43:17 am »
Oh! So I was wrong maybe... But why does it works?
As example i'm passing TLog objects to functions as a value parameter... So when I call the procedure toLog(msg : string); it add the string correctly to the object by TStringList.Add and the Object itself is modified ...

I'm gonna read those ressources carefully !

Thanks !

Zoran

  • Hero Member
  • *****
  • Posts: 1988
    • http://wiki.lazarus.freepascal.org/User:Zoran
Re: (SOLVED) Pass by reference
« Reply #5 on: June 22, 2011, 09:14:07 am »
Oh! So I was wrong maybe... But why does it works?
As example i'm passing TLog objects to functions as a value parameter... So when I call the procedure toLog(msg : string); it add the string correctly to the object by TStringList.Add and the Object itself is modified ...

I'm gonna read those ressources carefully !

Thanks !

Your code works as it should. There is nothing wrong in it.

The parameters can be passed to routine (function or procedure) as value parameters (that is "by value") or variable parameters ("by reference"). When we pass by value, then we can consider that when the routine is called, then a local variable is created in the routine and value of passed parameter is copied to this variable, so when we return from routine, the modified value of parameter (actually, only the value of this local variable in routine was modified) is lost, BUT if passed variable is a pointer (and note that object are pointers too), then this copied value is adress of referenced object and our new variable, with local scope in called routine holds the same adress (so, it points to same object in memory), doesn't it? Therefore, the actual object is same, even though we passed the pointer to it by value. Changes made in routine to referenced object are made to same object, because it was same adress got copied to local variable, so local variable points to same place in memory, to same object.

That is the reason your programme behaves this way. I hope this was not too confusing. ;)
Swan, ZX Spectrum emulator https://github.com/zoran-vucenovic/swan

Jell0wed

  • New Member
  • *
  • Posts: 28
  • I love cookies.
Re: (SOLVED) Pass by reference
« Reply #6 on: June 22, 2011, 02:43:26 pm »
I think I got it!

Here's a little bit of my code...
Code: Text  [Select][+][-]
  1. Type
  2.   TLog = class
  3.   private
  4.     logMsg : TStringList;
  5.   public
  6.     //constructor right here
  7.     procedure toLog(msg : string); //used procedure
  8.   end;
  9.  
  10. implementation
  11.  
  12. procedure TLog.toLog(msg : string);
  13. begin
  14.   logMsg.Add(msg);
  15.   writeln(msg); //basically, that's only what this function does :o)
  16. end;
  17.  

Then in my program execution :
Code: [Select]
Uses
   Logging;

procedure doSomething(log : TLog); //the argument is correctly passed by value isn't it?
begin
  log.logMsg('this is modifying the object itself...');
end;
//lets say the program execution starts here
var
  log : TLog;
begin
  log := TLog.Create('filename');
  doSomething(log);
  log.OutputMsgs; //will show "this is modifying the object itself..."
end.

This is basically what my program does... so if I understand correctly, objects are passed by pointers when we're dealing with routines (random question: is it to save space in memory and to have a faster execution time?), so that's why the doSomething function can modify the log variable itself, because it's modifying the object that the pointers points to ?

So let's say I modified the log : TLog value for a string value...
Code: [Select]
procedure doSometing(str : String);
begin
   str := 'doSomething procedure';
end;

//program starts here
var
   str : string;
begin
  str := 'main function';
  doSomething(str); //that wont work, it will work only if the procedure prototype would be this : procedure doSometing(var str : String);
  writeln(str); //would show "main function"
end;

Am I right ?

garlar27

  • Hero Member
  • *****
  • Posts: 652
Re: (SOLVED) Pass by reference
« Reply #7 on: June 22, 2011, 02:49:47 pm »
Yes, you are.

Jell0wed

  • New Member
  • *
  • Posts: 28
  • I love cookies.
Re: (SOLVED) Pass by reference
« Reply #8 on: June 22, 2011, 03:13:58 pm »
Thanks to both of you! :)

 

TinyPortal © 2005-2018