Pass and return by-value for structures
Posted: Sun Jul 15, 2018 5:37 am
Passing structures to functions is already possible through pointers. This is fine except in the case where we actually want a copy:
We can already make copies ourselves through CopyStructure() but this is tedious and requires resource tracking of the pointer passed into the function to guarantee its lifetime
Passing pointers is optimal for performance but adds a level of optimization which which is dangerous and often unnecessary. Note that resources will need to be tracked or copied in the event that data is passed on to threads or leaves scope which often makes this optimization redundant.
Pass-by-value is much simpler for these scenarios and the intent is clear. You are asking for and will receive a copy with a known lifetime as it will exist on the stack. (Note that collections contained therein are references on the heap but this requires its own consideration):
Notice that we can already copy structures through assignment. If only we could get that result from a function:
Returning a structure is much more tedious. We must either pass it in as an argument:
Or return it as memory on the heap which is both slower and requires resource management:
All of this can be avoided by returning by value:
Possibly even from another function:
Clearly there are performance penalties to these copy operations, especially when the lifetime is fleeting. But the advantages are real by simplifying resource management for those who are new to programming and providing another useful tool in the toolbox for those more experienced.
Code: Select all
Procedure FuncA(*arg.Struct)
Protected localArg.Struct
CopyStructure(*a,@localArg,SizeOf(Struct))
...
EndProcedure
Passing pointers is optimal for performance but adds a level of optimization which which is dangerous and often unnecessary. Note that resources will need to be tracked or copied in the event that data is passed on to threads or leaves scope which often makes this optimization redundant.
Pass-by-value is much simpler for these scenarios and the intent is clear. You are asking for and will receive a copy with a known lifetime as it will exist on the stack. (Note that collections contained therein are references on the heap but this requires its own consideration):
Code: Select all
Procedure FuncA(arg.Struct)
...
EndProcedure
Code: Select all
Structure Struct
value.i
EndStructure
a.Struct
a\value=123
b.Struct
b=a
Debug b\value
Code: Select all
Structure Struct
value.i
EndStructure
Procedure FuncA(*a.Struct)
*a\value=123
EndProcedure
a.Struct
FuncA(@a)
Debug a\value
Code: Select all
Structure Struct
value.i
EndStructure
Procedure.i FuncA()
Protected *a.Struct
*a=AllocateStructure(Struct)
*a\value=123
ProcedureReturn *a
EndProcedure
*a.Struct=FuncA()
Debug *a\value
FreeStructure(*a)
Code: Select all
Structure Struct
value.i
EndStructure
Procedure.Struct FuncA()
Protected a.Struct
a\value=123
ProcedureReturn a
EndProcedure
Debug FuncA()\value
Code: Select all
Procedure.Struct FuncA()
ProcedureReturn FuncB(1, 2, 3)
EndProcedure