String::empty or String()?


#1

I have noticed that the trend in JUCE is now to replace all (most?) of the occurrences of String::empty with String() (and similar cases, like var::null that is being replaced with var() )

In one of the latest commit, I noticed that the following line

expect (JSON::parse (String::empty) == var::null);

has been changed to:

expect (JSON::parse (String::empty) == var());

Thus removing var::null, but leaving String::empty.

Now I wonder: how does one choose whether to use the static member or the default constructor?

As a side question, is the page with the code conventions used in JUCE still available somewhere? I searched for it hoping to find my answer there, but haven’t been able to find it


#2

Hi yfede,

I can’t answer the first question, but for the side question, they are still in the same place - http://www.juce.com/learn/coding-standards


#3

Prefer String() and var()
Avoid String::empty and var::null

It’s potentially unsafe to use String::empty and var::null in code which may be invoked from a static constructor. Not a danger for most code, but no reason to risk it.

But mainly because using a locally-created unnamed temporary gives the compiler more scope to optimise it out, because it doesn’t have to worry about the implications of referencing a shared global memory address.

I’ve been gradually removing String::empty in bits of code that I’m changing for other reasons but haven’t yet bothered to sweep the whole codebase for it, so you’ll still see a few uses of it scattered around.


#4

The comment above String::empty should be amended :

   /** This is an empty string that can be used whenever one is needed.

        It's better to use this than String() because it explains what's going on
        and is more efficient.
    */
    static const String empty;

#5

Ah, thanks! Didn’t realise that comment was still there, will update it!


#6

Ok, got it, thanks @jules

Just for the sake of discussing this thoroughly, would the problems with usage by static constructors be resolved if we had the following static empty() method instead of the current empty static member?

static const String& String::empty ()
{
    static const String emptyInstance;
    return emptyInstance;
}

I’m asking, because this could come handy in other circumstances, for example if I end up with classes that have a costly (or private) default constructor and still I want to have something like a “null” or “empty” instance always readily available.


#7

Yes, that would be safe, at the expense of performance, because the compiler will generate a whole bunch of boilerplate code inside that function involving atomic ops + mutexes that will have to run every time you call it. Whereas calling String() is also a function call, but avoids all that overhead.


#8

Yes yes, sure, I was absolutely not implying that it should be actually done for String!

I used String just as an example because that’s what we were talking about.

Like I said, the only use case I see for this is when the default constructor for the class is too costly to be called every time, or when it is private with good reasons for being so. In that case, the static method may be the lesser evil of all alternatives.


#9

Yes, local statics are great for that kind of thing in general.