Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

Even languages where you have explicit pointer manipulation like C it's always passed by value (you can pass them by reference but that's not the default behavior).

What is the benefit of this, why are so many languages passed by values and why are others passed by reference ? (I understand Haskell is passed by reference though I'm not sure).

share|improve this question
3  
void acceptEntireProgrammingLanguageByValue(C++); –  Thomas Eding Jun 19 '12 at 23:24
3  
It could be worse. Some old languages also allowed for call by name –  hugomg Jun 19 '12 at 23:50
12  
Actually, in C you can't pass by reference. You can pass a pointer by value, which is very similar to pass-by-reference, but not the same thing. In C++, though, you can pass by reference. –  Mason Wheeler Jun 20 '12 at 0:27
    
@Mason Wheeler can you elaborate more or add some link, beacuase your statement is not clear to me as I'm not C/C++ guru, just a regular programmer, thanks –  Betlista Nov 9 '12 at 11:38
    
@Betlista: With pass by reference, you can write a swap routine that looks like this: temp := a; a := b; b := temp; And when it returns, the values of a and b will be swapped. There's no way to do that in C; you have to pass pointers to a and b and the swap routine has to act on the values they point to. –  Mason Wheeler Nov 9 '12 at 11:54

7 Answers 7

Pass by value is often safer than pass by reference, because you cannot accidentally modify the parameters to your method/function. This makes using the language simpler to use, since you don't have to worry about the variables you give to a function. You know they won't be changed, and this is often what you expect.

However, if you want to modify the parameters, you need to have some explicit operation to make this clear (pass in a pointer). This will force all your callers to make the call slightly differently (&variable, in C) and this makes it explicit that the variable parameter may be changed.

So now you can assume that a function will not change your variable parameter, unless it is explicitly marked to do so (by requiring you to pass in a pointer). This is a safer and cleaner solution than the alternative: Assume everything can change your parameters, unless they specifically say they can't.

share|improve this answer
3  
+1 Arrays decaying to pointers present a notable exception, but the overall explanation is good. –  dasblinkenlight Jun 19 '12 at 21:29
3  
@dasblinkenlight: arrays are a sore spot in C :( –  Matthieu M. Jun 20 '12 at 7:11
1  
+1 for taking up the point with local variables –  Niklas rtz Jun 26 '12 at 7:55

Call-by-value and call-by-reference are implementation techniques that were mistaken for parameter-passing modes a long time ago.

In the beginning, there was FORTRAN. FORTRAN only had call-by-reference, since subroutines had to be able to modify their parameters, and computing cycles were too expensive to allow multiple parameter-passing modes, plus not enough was known about programming when FORTRAN was first defined.

ALGOL came up with call-by-name and call-by-value. Call-by-value was for things that were not supposed to be changed (input parameters). Call-by-name was for output parameters. Call-by-name turned out to be a major crock, and ALGOL 68 dropped it.

PASCAL provided call-by-value and call-by-reference. It did not provide any way for the programmer to tell the compiler that he was passing a large object (usually an array) by reference, to avoid blowing the parameter stack, but that the object should not be changed.

PASCAL added pointers to the language design lexicon.

C provided call-by-value, and simulated call-by-reference by defining a kludge operator to return a pointer to an arbitrary object in memory.

Later languages copied C, mostly because the designers had never seen anything else. This is probably why call-by-value is so popular.

C++ added a kludge on top of the C kludge to provide call-by-reference.

Now, as a direct result of call-by-value vs. call-by-reference vs. call-by-pointer-kludge, C and C++ (programmers) have horrible headaches with const pointers and pointers to const (read-only) objects.

Ada managed to avoid this whole nightmare.

Ada does not have explicit call-by-value vs. call-by-reference. Rather, Ada has in parameters (which may be read but not written), out parameters (which MUST be written before they can be read), and in out parameters, which may be read and written in any order. The compiler decides whether a particular parameter is passed by value or by reference: it is transparent to the programmer.

share|improve this answer
1  
+1. This is the only answer I've seen on here so far that actually answers the question and makes sense and does not use it as a transparent excuse for a pro-FP rant. –  Mason Wheeler Jun 20 '12 at 0:37
    
+1 for mentioning the stack. –  james Jun 20 '12 at 1:07
4  
+1 for "Later languages copied C, mostly because the designers had never seen anything else." Every time I see a new language with 0-prefixed octal constants I die a little inside. –  librik Jun 20 '12 at 11:58
    
Also, not sure about early Pascal, but in modern Pascal (Delphi, etc) you can pass a large object such as an array by reference but keep it immutable by using the const keyword on the parameter. –  Mason Wheeler Jun 20 '12 at 13:12
2  
This could be the first sentence of the Bible of programming: In the beginning, there was FORTRAN. –  user39685 Jan 18 '13 at 15:06

Pass by reference allows for very subtle unintended side effects that are very difficult to next to impossible to trace down when they start causing the unintended behavior.

Pass by value, especially final, static or const input parameters makes this entire class of bugs disappear.

Immutable languages are even more deterministic and easier to reason about and understand what is going in and what is expected to be coming coming out of a function.

share|improve this answer
6  
It's one of those things that you figure out after trying to debug 'ancient' VB code where everything is by reference as default. –  jfrankcarr Jun 19 '12 at 19:59
    
Maybe it's just that my background is different, but I have no idea what sort of "very subtle unintended side effects that are very difficult to next to impossible to trace down" you're talking about. I'm used to Pascal, where by-value is the default but by-reference can be used by explicitly marking the parameter, (basically the same model as C#,) and I've never had that cause problems for me. I can see how it would be problematic in "ancient VB" where by-ref is the default, but when by-ref is opt-in, it makes you think about it while you're writing it. –  Mason Wheeler Jun 20 '12 at 0:32
3  
@MasonWheeler what about newbies that come along behind you and just copy what you did without understanding it and start manipulating that state all over the place indirectly, real world happens all the time. Less indirection is a good thing. Immutable is best. –  Jarrod Roberson Jun 20 '12 at 0:47
1  
@MasonWheeler The simple alias examples, like the Swap hacks that don't use a temporary variable, though not likely to be a problem themselves, show how hard a more complex example might be to debug. –  Mark Hurd Jun 28 '12 at 2:16

There is different behavior depending on the calling model of the language, the type of arguments and the memory models of the language.

With simple native types, passing by value allow you to pass the value by the registers. That can be very fast since the value aren't need to be loaded from memory neither save back. Similar optimization is also possible simply by reusing the memory used by the argument once the callee is done with it, without risking to mess with the caller copy of the object. If the argument was a temporary object, you would have probably save a full copy doing so (C++11 make this kind of optimization even more obvious with the new right-reference and its move semantic).

In a lot of OO languages (C++ is more an exception in this context), you cannot passed an object by value. You are force to pass it by reference. This make the code polymorphic by default and are more inline with the notion of instances proper to OO. Also, if you want to pass by value, you must make a copy yourself, acknowledging the cost of performance that generated such action. In this case, the language choose for you the approach that is more likely to give you the best performance.

In case of functional languages, I guess passing by value or reference is simply a question of optimization. Since the functions in such language are pure and so free of side effects, there is really no reason to copy the value except for speed. I'm even pretty sure that such language often shared the same copy of objects with the same values, a possibility available only if you used a pass by (const) reference semantic. Python also used this trick for integer and common strings (like methods and class names), explaining why integer and strings are constant objects in Python. This also help to optimize the code again, by allowing for example pointer comparaison instead of content comparaison, and doing lazy evaluation of some internal data.

share|improve this answer

Why are so many languages passed by value?

The point of breaking up large programs into small subroutines is that you can reason about the subroutines independently. Pass-by-reference breaks this property. (As does shared mutable state.)

Even languages where you have explicit pointer manipulation like C it's always passed by value (you can pass them by reference but that's not the default behavior).

Actually, C is always pass-by-value, never pass-by-reference. You can take an address of something and pass that address, but the address will still be passed by value.

What is the benefit of this, why are so many languages passed by values and why are others passed by reference ?

There are two main reasons for using pass-by-reference:

  1. simulating multiple return values
  2. efficiency

Personally, I think #1 is bogus: it's almost always an excuse for bad API and/or language design:

  1. If you need multiple return values, don't simulate them, just use a language which supports them.
  2. You can just as well simulate multiple return values by packaging them into some lightweight data structure such as a tuple. This works particularly well if the language supports pattern matching or destructuring bind. E.g. Ruby:

    def foo
      # This is actually just a single return value, an array: [1, 2, 3]
      return 1, 2, 3
    end
    
    # Ruby supports destructuring bind for arrays: a, b, c = [1, 2, 3]
    one, two, three = foo
    
  3. Oftentimes, you don't even need multiple return values. For example, one popular pattern is that the subroutine returns an error code and the actual result is written back by reference. Instead, you should just throw an exception if the error is unexpected or return an Either<Exception, T> if the error is expected. Another pattern is to return a boolean which tells whether the operation was successful and return the actual result by reference. Again, if the failure is unexpected, you should throw an exception instead, if the failure is expected, e.g. when looking up a value in a dictionary, you should return a Maybe<T> instead.

Pass-by-reference may be more efficient than pass-by-value, because you don't have to copy the value.

(I understand Haskell is passed by reference though I'm not sure).

No, Haskell is not pass-by-reference. Nor is it pass-by-value. Pass-by-reference and pass-by-value are both strict evaluation strategies, but Haskell is non-strict.

In fact, the Haskell Specification doesn't specify any particular evaluation strategy. Most Hakell implementations use a mixture of call-by-name and call-by-need (a variant of call-by-name with memoization), but the standard doesn't mandate this.

Note that even for strict languages, it doesn't make sense to distinguish between pass-by-reference or pass-by-value for functional languages since the difference between them can only be observed if you mutate the reference. Therefore, the implementor is free to chose between the two, without breaking the semantics of the language.

share|improve this answer
5  
"If you need multiple return values, don't simulate them, just use a language which supports them." This is a bit of a strange thing to say. It's basically saying "if your language can do everything you need, but one feature that you'll probably need in less than 1% of your code--but you still will need it for that 1%--can't be done in a particularly clean way, then your language isn't good enough for your project and you should rewrite the whole thing in another language." Sorry, but that's just plain ridiculous. –  Mason Wheeler Jun 20 '12 at 0:35
    
+1 I totally agree with this point The point of breaking up large programs into small subroutines is that you can reason about the subroutines independently. Pass-by-reference breaks this property. (As does shared mutable state.) –  im_a_noob May 1 at 20:42

You can pass an expression by value, it's natural. Passing expression by (temporary) reference is... weird.

share|improve this answer
1  
Also, passing expression by temporary reference can lead to bad bugs (in stateful language), when you happily change it (since it's just temporary), but then it backfires when you actually pass a variable, and you must devise ugly workaround like passing foo+0 instead of foo. –  herby Jun 19 '12 at 21:23

If you pass by reference, then you are effectively always working with global values, with all of the problems of globals (namely scope and unintended side effects).

References, just like globals, are sometimes beneficial, but they shouldn't be your first choice.

share|improve this answer
3  
I assume you meant pass by reference in the first sentence? –  jk. Jun 19 '12 at 20:43
    
@jk: yes, thanks for catching that. –  jmoreno Jun 19 '12 at 21:25

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.