Question

Everyone knows that C/C++ function arguments are pass-by-value. So why do some people insist that correct style is to make a local copy of a function argument before modifying it? For example, they would write:

void baz(unsigned int *ptr)
{
  unsigned int *lPtr = ptr;
  for(int i = 0; i < 10; i++)
  {
      foo(*lPtr++);
  }
}

instead of:

void baz(unsigned int *ptr)
{
  for(int i = 0; i < 10; i++)
  {
      foo(*ptr++);
  }
}

It seems like the second way is easier to read since it is one less variable.

Was it helpful?

Solution

The only justification is for much larger functions, someone may add new functionality to the bottom of a function not realizing that the parameter was modified or made invalid earlier up.

Imagine:

int bighorriblefunction(const char * astr)
{
  // hundreds of lines of horribleness
  while ( * astr ) { /* something */  ++ astr ; }

  // more pages of code

  /** author two adds later */
  if ( ! strcmp(astr, "magicvalue") ) { /** do this really important thing **/  return 1 ; }
  return 0 ;
}

Its going to take author two a while to realize that the new code is never going to run.

OTHER TIPS

They do it because the original value is useful when debugging.

I think it is because the author of the code wrote the declaration of the variable in the first version of baz(), and then he refactored the code, which moved the code in the for loop into the function foo(), and the author mistakenly didn't remove the variable. The variable is pure waste. Hope this helps!

That's a poor man's version of separation of interface from implementation.

Supposed you wrote this code a year ago:

class Foo
{
public:
    void bar( const char *where )
    {
        // The dreaded copy
        const char *destination = where;

        // The actual implementation that in the real world may take 500 
        // lines of code with 20 references to the variable destination
    }
};

And now, a year later, you want to make the parameter where optional, defaulted to a member variable of the class. Alas, you don't remember what exactly those 500 lines of code do! Fortunately, you are saved by the virtue of the parameter being copied before use:

class Foo
{
public:
    void bar( const char *where = NULL)
    {
        // Hooray! I only have to change 1 line here!
        const char *destination = where? where : m_MyHomeDir.c_str();

        // The actual implementation that in the real world may take 500 
        // lines of code with 20 references to the variable destination
    }

private:
    std::string m_MyHomeDir;
};

If you're doing it in C++, just use:

std::for_each(ptr, ptr+10, foo);

I know, that doesn't answer the question directly, but does point toward the fact that it should usually be irrelevant. If it is relevant you probably need to rewrite the code in general.

I'm not clear who these "some people" are (I've never heard of this demand), but the only legitimate reason I can think of for it is that it slightly aids in debugging: if the debugger stops the function in the middle, you can see the argument values it was originally called with. However in most cases you can achieve the same thing by just moving up one call frame and looking at the values of the expressions that were passed to the function.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top