Creating write-only code: the Reference (&) Operator

Write-only code is a term used to describe code that can easily be written, but that no one but the original author can easily read. Since invariably far more time is spent reading code than writing it, this is NOT a positive term.

Recently, while participating in a code review, I was reminded of one of my least-favorite C++ features -- the ability to use a reference declarator in a function. Most code that needs to change a variable of the caller is written like this:

 void foo(long *a)
{
    *a = 3;
}

void caller()
{
    long var = 0;
    foo(&var);
}

However, by using the syntax "type-id & cast-expression" in the function declaration, you can write this:

 void bar(long &a)
{
    a = 3;
}

void hard_to_read_caller()
{
    long var = 0;
    bar(var);
}

If you look at the assembly code generated, it's exactly the same in both cases. The (x86, unoptimized) calling code looks like this:

 lea         eax,[ebp-8]
push        eax
call        @ILT+459(?foo@@YGXPAJ@Z)

So what's the difference? In the first example, it's obvious from the calling code that the variable 'a' can get modified. You don't know for sure that it will, but since you're obviously passing the address of the variable, you know it's a possibility. Now you can go check the definition of 'foo' to see how it might change your variable.

In the second example, there is no clue at all from the calling code. The call to bar looks no different than if bar were defined as 'void bar(long a)'. Without looking up the function prototype for bar, you'd assume that var won't be modified. In short, this is write-only code.

This is one of the (many) things that the C# team got right. You must use the ref or out keywords from the calling code when passing variables to a function that can change them (ref for input/output variables, out for output-only variables).