Const, invariant, strings and "constant data need never be copied"

Janice Caron caron800 at googlemail.com
Sat Nov 3 00:20:58 PDT 2007


On 11/3/07, Stewart Gordon <smjg_1998 at yahoo.com> wrote:
> > All of my D2 code compiled without change.
>
> Because your D2 code doesn't manipulate strings?

No, because I declared all my strings as string or wstring, not char[]
or wchar[]. And because I use, and assume, D's copy-on-write protocol.


> If /all/ strings are invariant, then you're very limited in what
> manipulations you can perform.

That's not true. You can do as much manipulation as you want at
creation-time. Only once the manipulation is "finished" do you cast
the result to string. (And that behavior is identical between const()
and invariant(), by the way, so the change to invariant() makes zero
difference to the source code at this point, except that you now have
the option of using the assumeUnique() function).


> Only in the cases where ensuring that the reference is unique is possible.

It's always possible. Just write an opening brace, do all your string
creation, assign the string to a string variable declared outside the
scope, then write a closing brace. Viola - invariance guaranteed,
because all the other references used in creation just went out of
scope.

Note that it is perfectly permissible to have multiple references to
an an invariant string anyway - providing that all of those references
are themselves declared invariant. It's only non-invariant references
which are prohibited, which is why they're the ones you have to lose
at the scope boundary.


> There's the problem.  You've made the code more complicated to make the
> final copy conditional on something actually changing.

Of course. That /is/ the copy-on-write protocol. If nothing changes,
return the original.


> Moreover, your code loops twice, first to see if there's anything to change
> and then to perform the conversion.  This in itself would take a performance
> hit.

I could have used the new munch() function instead of the first loop,
but I didn't think of it at the time I wrote the example.


> You miss the point.  My example is of ad-hoc code to perform the conversion
> in place, because it is the most efficient mechanism with the constraints
> under which the application will ever perform it.  Data always loaded into
> RAM immediately before the conversion, and no desire to keep the 'before'
> data once the conversion has happened.

Well then there's no problem anyway. For the whole time that your
string is "under construction", then it's not a string, it's a
(mutable) array of chars. Just keep it as such, until you've finished
building the string. Then do can do everything in place.

But note that if you want to do in-place manipulation of chars, then
std.string.replace() is NOT the function to use, because that
(possibly) makes a copy. Instead, you would have a replacing loop, or
write your own in-place-replace function which operates on char arrays
(or templatized for arrays in general)


> Well, I wasn't writing a string function there.

Then you shouldn't be calling std.string functions. What you need are
array functions.



More information about the Digitalmars-d mailing list