Is the [Ref] attribute for const record parameters useful?
Asked Answered
D

2

11

With the latest Delphi version (Berlin/10.1/24), is the [Ref] attribute really necessary?

I ask this because the online doc says:

Constant parameters may be passed to the function by value or by reference, depending on the specific compiler used. To force the compiler to pass a constant parameter by reference, you can use the [Ref] decorator with the const keyword.

Dmz answered 2/12, 2016 at 9:58 Comment(3)
You may find the answer here: Can I force const to pass by reference (aka the missing in parameter).Unsuspecting
That is, const records <= SizeOf(pointer) are passed by value. If you want to ensure that a reference is passed, use the [ref] attribute.Unsuspecting
ok that sounds very sensible, and makes me think I can give up on using the Ref attribute for const record parameters.Dmz
Y
12

It's pretty much as described by the documentation. You'd use [ref] if you had a reason to enforce the argument to be passed by reference. One example that I can think of is for interop. Imagine you are calling an API function that is defined like this:

typedef struct {
    int foo;
} INFO;

int DoStuff(const INFO *lpInfo);

In Pascal you might wish to import it like this:

type
  TInfo = record
    foo: Integer;
  end;

function DoStuff(const Info: TInfo): Integer; cdecl; external libname;

But because TInfo is small, the compiler might choose to pass the structure by value. So you can annotate with [ref] to force the compiler to pass the parameter as a reference.

function DoStuff(const [ref] Info: TInfo): Integer; cdecl; external libname;
Yapok answered 2/12, 2016 at 10:7 Comment(11)
Thanks for that. "But because TInfo is small, the compiler might choose to pass the structure by value." You have seen this documented somewhere, or did you observe this in the compilation output?Dmz
The documentation is pretty unclear. Only the 32 bit Windows compiler's ABI is remotely documented by Emba, and then not terribly well. The coverage of const arguments is, er, well, incomplete. But yes, records can be pushed by value or by reference, depending on their size. For the code in my answer, without [ref], the two Windows compilers will pass by value. Add another int to the struct and the 32 bit compiler passes by reference, but the 64 bit compiler by value. Add another one and both pass by reference.Yapok
ha that is pretty much exactly what I was trying to find out. ThanksDmz
It remains to be noted that const, in this context, is not very useful anyway, so I would explicitly declare David's example as function DoStuff(var Info: TInfo)... or function DoStuff(Info: PInfo).....Rotherham
@RudyVelthuis The example is not meant to be realistic. Imagine it's a struct that is passed as an IN parameter. And so const is appropriate. So, var and PInfo are not appropriate.Yapok
When dealing with APIs, it is my experience that const is not useful at all. If the struct has to be passed by reference, it suffices to use var.Rotherham
@rudy That tells the caller that the value can be modified. A bad idea.Yapok
The parameters give the programmer useful information.Yapok
In the case of an API, I don't think it matters. If you must pass by reference, use var or out. The attribute is a bit of an unnecessary kludge, IMO.Rotherham
Marco Cantu states: "Finally there is a fairly unknown option for passing an object as parameter, called constant reference and written as [ref] const. When a parameter is passed as constant reference it behaves similarly to a passing by reference (var), but it allows more flexibility in the type of the parameter you are passing, not requiring an exact type match (as passing an object of a subclass is allowed)."Kingship
So, [ref] has a double purpose.Kingship
C
1

Another example is the new FreeAndNil procedure declaration in Delphi 10.4 in SysUtils.pas, which now finally ensures that only TObject descendants can be used with FreeAndNil. In previous Delphi versions, you could pass anything to this function, even if it didn't make sense.

Colner answered 27/5, 2020 at 8:0 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.