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).

Comments

  • Anonymous
    September 18, 2006
    The comment has been removed
  • Anonymous
    September 18, 2006
    The comment has been removed
  • Anonymous
    September 18, 2006
    The Reference Operator in C++ is very useful if you don’t want a copy of your data type. To prevent the function from writng you can use the const keyword. The same is true in C#. If you use reference types the function can change your variable.
  • Anonymous
    September 18, 2006
    Hmph. I'm sure there are plenty of other ways in C# to write write-only code. e.g. inappropriate overloading of other operators.

    Yes, you shouldn't use any of them. Yes, decent software projects will have coding guidelines outlawing them. But then, most people don't use non-const reference parameters in C++, and most decent software projects will have guidelines not to use them.

    And the C# solution isn't "all that" either. Although callees cannot change the object the caller's variable points to, they can still modify objects by calling methods that alter them (mutators). Without an equivalent of C++'s logical constness, there's no way of knowing whether or not the object you pass to a function will in any way resemble itself by the time the function returns.
  • Anonymous
    September 19, 2006
    I'm not sure I get how the const operator of C++ guarantees anything, either. If you pass a const pointer to a function, that function can still change the data that's being pointed to.

    To the Intellisense comment: yes, this can help a lot. But Intellisense or any other development environment isn't a good substitute, I think, for being able to just read through the code.
  • Anonymous
    September 19, 2006
    Re the const operator and pointers

    Remeber

    (const int* pI) != (const int* const pI)

    And if you don't know the difference I sugest revisiting a good C++ book!

    In truth I've met very few people who remember that to make a pointer and it's contents truelly const you have to use the second syntax, but it's part of the language...
  • Anonymous
    September 19, 2006
    The comment has been removed
  • Anonymous
    September 19, 2006
    In fact, the best explanation is probably on the C++ faq lite -

    http://www.parashift.com/c++-faq-lite/const-correctness.html
  • Anonymous
    October 03, 2006
    Just use Objective-C. It's much better :-)This all gets to a more general point. You should be able to understand what source code is doing without having to refer to the .h file. When someone says "Didn't you check the .h file?" I want to strangle them. I don't have to refer to a dictionary or encyclopedia to understand a well written book. I should similarly be able to understand source code without having to check other references. It should be obvious from the calling code what types the parameters are and whether they might be altered.JR
  • Anonymous
    June 13, 2009
    PingBack from http://barstoolsite.info/story.php?id=1413