To elaborate on 440bx's statement
The below program is erroneous.
"ChangeFoo" make changes to Foo, while "OptimizeMe" expects Foo to be unchanged.
Currently, it will most likely work (with any version and settings of Fpc). But that is not guaranteed.
If/Once the optimizer in Fpc gets better, it could very well be, that the below Program
- writes "2" to the console twice.
- does other unexpected things
program Test;
type TFoo = record a,b: Integer; end;
var Foo: TFoo;
procedure ChangeFoo;
begin
Foo.a := 1;
end;
procedure OptimizeMe(const x: TFoo);
begin
writeln(x.a); // writes 2
ChangeFoo;
writeln(x.a); // in future, maybe writes "2" again, or "1" at random...
end;
begin
Foo.a := 2;
Foo.b := 3;
OptimizeMe(Foo);
end.
https://www.freepascal.org/docs-html/ref/refsu67.htmlNote that specifying const is a contract between the programmer and the compiler. It is the programmer who tells the compiler that the contents of the const parameter will not be changed when the routine is executed
"ChangeFoo" is executed when (while) "OptimizeMe" still runs.
The programmer who wrote the "const" promised, they would not change "Foo" during this time. And yet, they do.
The compiler would have been in its right to cache the value "2" and use it
Mind, that while currently it accidentality works for records (at least as far as I tested), it does already break for other types (ansistrings, dyn-array, any refcounted, ...).
And there have been real life apps that crashed due to the above programmers mistake.
So change everything to "const" => and many existing apps will fail.
Mind, btw that in many cases (depends on OS/CPU) a record as the above (up to 2 pointers in size) may be passed in registers. And that means, even though it is a copy, it may be of the same speed (in terms of optimizations).