Can anyone show an example when copying a string on constref is a necessery move?
It all depends on the level of optimization, and other settings. Maybe even compiler version.
To demonstrate the effect of the missing "uniquestring", I used the PAnsiChar version.
The below passes a pointer to 'a', but prints '5' (which is something random that went in place of the released string).
If you comment the first line, and uncomment the 2nd, then it prints 's', the first char of the 2nd string.
Program foo; {$mode objfpc}{$H+}
uses SysUtils;
var
S, S2: AnsiString;
//procedure P1(constref Ch: AnsiChar);
procedure P1( Ch: PAnsiChar);
begin
s := ''; s2 := 'something else' + IntToStr(random(9)); // avoid compiletime const eval
//s := 'something else' + IntToStr(random(9)); // avoid compiletime const eval
Writeln(Ch^);
end;
begin
s := 'abcdef' + inttostr(random(9)); // avoid compiletime const eval
P1(@S[1]);
readln;
end.
In real life, I have seen stuff like this when using "const s: ansistring"
- because that is a much more common construct
- because that does not do the uniquesting (in fact it is used because it does not)
And last time I saw it, the string was a field in an object. It wasn't directly modified by the called procedure, but that procedure had callbacks (events that it called, and about 10 calls deep into the stack on the callback was some code that modified the field.
@PascalDragon: I only partly agree with your statement.
1) UniqueString is overkill. (for constref)
It is not only a reference. It is also const.
It does only need an Increment-refcount. If anyone else writes to it, and the refcount is greater 1 then the other will make a copy of their own.
Sure you can bypass that with pchar magic. But then you intentionally break protection.
The general idea is, that having any code that holds a ref to a string, can trust it. If the caller in this case holds that ref, then the callee is fine by those means.
( That differs for a "var c: ansichar" param (or "out"), because then "c" itself can be changed, and at that point it must act on a uniquely referenced copy of the string)
2) It is inconsistent....
While it is nice that there is safety first...
constref is a form of const.
const does not add that form of protection.
In fact it has been stated countless times, that const is a contract where the user (programmer) tells the compiler, that the variable will not change.
And "will not change" includes, that it will not be changed by any code while the called code is running (has not returned to its caller).
With const too, as I stated other code may change (breaking the contract) a string that was passed without protection. And that is by design.
Why is that design not applied for constref?
I may have missed something, but I though constref is the same optimization as const? Except for adding a ref?
EDIT /APPEND
And then, if the string is protected because "constref" takes a pointer (reference) to a char in the string, then why is it not protected if
takes the same pointer? (only without read-only protection...)