On 01.04.2017 09:59, Ryan Joseph wrote: > >> On Apr 1, 2017, at 2:46 PM, Sven Barth via fpc-pascal >> <fpc-pascal@lists.freepascal.org> wrote: >> >> I haven't looked at it in detail, but it could be that both have similar >> efficiency. You could also add "inline" to the MakePoint function which >> should get rid of a potential temporary variable if the compiler doesn't do >> that already anyway. >> Alternatively you could also declare a constructor "TPoint.Make" or so (that >> despite its name doesn't do any dynamic memory allocation either) which you >> can declare as inline as well. > > How is the constructor any different from the function?
In case of constructor vs. global function the encapsulation is more clear. In case of constructor vs. class function there isn't really that much difference except that through the name alone ("constructor blabla") it's clear what the purpose of the function should be. (Though I now also noticed that you can't use "inline" with constructors...) >> >> In the end you can always check the assembler code. > > Not sure how to do that or what to look for. It appears to me without knowing > how the compiler works that there would be some allocating and copying of > memory which is more overhead than assigning a value directly. Maybe it’s > totally trivial but if it is it’s something I should cut out of my design > going forward. The compiler keeps the assembler code with line information around if you pass "-al". If you are so concerned about the differences in performance regarding using a setter and a construction function you should really learn at least in principle how typical assembler code generated by the compiler looks like (same for your query about dynamic arrays by the way, though there you should also take a look at the implementation of the RTL). Here is an example compiled without optimizations aside from inline: === code begin === # [47] p.&Set(42, 21); movq $U_$P$TRECFUNCS_$$_P,%rax movl $21,%edx movl $42,%esi movq %rax,%rdi call P$TRECFUNCS$_$TPOINT_$__$$_SET$LONGINT$LONGINT # [48] p := TPoint.Make(42, 21); leaq -8(%rbp),%rdi movl $21,%edx movl $42,%esi call P$TRECFUNCS$_$TPOINT_$__$$_MAKE$LONGINT$LONGINT$$TPOINT movq -8(%rbp),%rax movq %rax,U_$P$TRECFUNCS_$$_P # [49] p := TPoint.Make2(42, 21); movl $42,U_$P$TRECFUNCS_$$_P movl $21,U_$P$TRECFUNCS_$$_P+4 # [50] p := MakePoint(42, 21); movl $21,%esi movl $42,%edi call P$TRECFUNCS_$$_MAKEPOINT$LONGINT$LONGINT$$TPOINT movq %rax,U_$P$TRECFUNCS_$$_P # [51] p := MakePoint2(42, 21); movl $42,U_$P$TRECFUNCS_$$_P movl $21,U_$P$TRECFUNCS_$$_P+4 === code end === "&Set" is essentially your "SetPoint" method. "Make" is a constructor. "Make2" is a static class function with "inline". "MakePoint" is your creation function and "MakePoint2" is the same with an inline modifier. As you can see the two inline variants ("Make2" and "MakePoint2") are the most effective as there's no call and only the two loads of the values. Regards, Sven _______________________________________________ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal