2

Possible Duplicate:
Is it better in C++ to pass by value or pass by constant reference?
When to pass by reference and when to pass by pointer in C++?

I am fairly new to c and c++ and I have the following question with regards to passing parameters to functions and thought it best to ask here and come straight to the source of the knowledge from the gurus.

When should I pass parameters by value and when sould they be passed by reference? And what is the most commonly used method in the real world?

Thanks in advance.

Community
  • 1
  • 1
Letholdrus
  • 1,261
  • 3
  • 20
  • 36

6 Answers6

4

Prefer pass by reference, usually one or more of:

  1. If it's big. (Definitely do this if it's const, do it anyway quite often though, depending on the rest of this list)
  2. If you want to edit it and make changes globally visible.
  3. If you want virtual functions to behave polymorphicly.
  4. In template code if you don't know what type(s) it's going to be.

Pass by value:

  1. If it's a trivial builtin type (e.g. int)
  2. If you don't want changes to be alter the original object.
  3. If you want to be able to pass temporaries in without having to make it const.
Flexo
  • 87,323
  • 22
  • 191
  • 272
  • Clarified the `const` point a bit better now. – Flexo May 14 '11 at 15:06
  • "make changes globally visible" is a bit of a red herring; your object may not have globally visible properties. – Lightness Races in Orbit May 14 '11 at 15:08
  • @Tomalak: How about "changes visible outside of the function" ? – Billy ONeal May 14 '11 at 15:10
  • There's no need to pass by reference big objects if the function is only called once a day. – John Dibling May 14 '11 at 15:12
  • @Billy: A bit better. "if you don't want changes to affect the original object" might be better still. – Lightness Races in Orbit May 14 '11 at 15:12
  • 1
    @John: That said, if you can deal with pass-by-reference-to-const then you should even if it is only called once a day -- tomorrow it might be called millions of times a day. – Billy ONeal May 14 '11 at 15:13
  • @John Dibbling - there's no harm in passing by reference either in that case though. My default choice is `const` reference and then from there I remove either `const` and/or the reference part if there's a reason to. – Flexo May 14 '11 at 15:14
  • @Billy: Doing something today in a micro optimized way because "tomorrow we may need it" is premature micro optimization by definition. There is no demonstrated need for this optimization. – John Dibling May 14 '11 at 15:15
  • @John - normally I'd agree on the premature micro optimisation thing, but in this instance I think `const` reference would have been a better default for C++ parameter passing were it not for the C legacy and retro-fitting `const` is so tedious... – Flexo May 14 '11 at 15:18
  • @John - worrying how reference vs value influences the call at the binary level is the *real* premature optimisation in this scenario. – Flexo May 14 '11 at 15:20
  • @awoodland: That's not what I'm "worried" about at all, if I'm worried about anything. – John Dibling May 14 '11 at 15:24
1

If the parameter is bigger than register and you're not modifying it, you should pass it as const reference. Of course, there are exceptional cases where you later create a copy or so, but in general this rule holds true.

For smaller types, it should not matter (i.e. const int& or int) should give the same result. To be safe, pass them by value anyway. For generic code, you can use the Boost Call Traits library which automatically decides whether to use by-reference or by-value.

If you want to modify the object, passing it in as reference allows you to modify it in-place, which is usually faster than returning a new one and overwriting the original one.

Anteru
  • 19,042
  • 12
  • 77
  • 121
  • I don't see how someone is supposed to make a call like this, given that C++ does not define a size of a register. (And on many architectures, such as x86, registers aren't used to pass arguments anyway) – Billy ONeal May 14 '11 at 15:04
  • Primitive types are register sized, for the most common platforms. The standard ABIs also typically pack a few parameters into registers, more so on x64. – Anteru May 14 '11 at 15:06
  • This borders on premature micro optimization. – John Dibling May 14 '11 at 15:08
  • 1
    Hu?`Pass int/float/double/etc. as value, and everything bigger as const reference& doesn't smell like "micro optimization" but rather as a good general rule-of-the-thumb. – Anteru May 14 '11 at 15:09
  • @Anteru: The standard ABIs used by both Linux/BSD/most posix boxes (cdecl), and by Windows (stdcall) both do not use registers to pass arguments. – Billy ONeal May 14 '11 at 15:10
  • Right, in 32-bit mode. On x64, they definitely use registers aggressively. – Anteru May 14 '11 at 15:11
  • @Billy the fact hasn't to do with register directly. It just means, copying something larger than the usual register size (32/64bit) is more expensive than just copying a pointer (that has register size and is equivalent to a reference, actually a reference is just a more comfortable syntax for a pointer). – Christian Rau May 14 '11 at 15:13
  • He did not mean registers directly. He just used the term register size for the machine word size, that is the size of a pointer (or reference). He didn#t say anything about explicit pass by register, which would be micro-optimization. – Christian Rau May 14 '11 at 15:14
  • @Christian: Then the answer should read "bigger than a primitive type" not "bigger than register" -- the register size of the particular machine you happen to be using today should not be the deciding factor in your code. – Billy ONeal May 14 '11 at 15:15
  • @Billy Ok, a bit wrong terminus. – Christian Rau May 14 '11 at 15:16
0

Pass by value unless you have a reason not to. Reasons not to:

  1. You want the function to change the object in some way. Pass by reference or by pointer.
  2. The object is "big." The precise definition of "big" will depend on your computer, your platform, the ramifications of making a copy of your object, etc. You will have to evaluate on a case-by-case basis. Pass by const reference.
  3. Making a copy of the object would do something "bad". For example, if by copying a file pointer object it creates another file, or by copying a synchronization object it creates a deadlock. Pass by const reference.
  4. You need polymorphic behavior on the passed-in object. Pass by reference or by pointer. Passing by value will slice the object.

Note that with #2 above, even if the object is big you may still want to pass by value. Passing by value is simpler therefore easier to maintain, and unless you have reason to believe that passing by value is creating an actual problem in your code, passing by const reference might be premature micro optiminzation. For example, if your function takes a parameter that is 64 bytes (or even 64k bytes) but that function is only called once a day, there's really no reason to pass by const reference. It saves you virtually nothing. Profile your code in release mode first, then optimize.

Community
  • 1
  • 1
John Dibling
  • 99,718
  • 31
  • 186
  • 324
0

By default, pass by const reference, except:

1) If you want an in/out or out parameter - one that gets changed by the function. In that case, use a non-const reference. 2) If you are passing an integer, float or pointer - pass by value.

Nemanja Trifunovic
  • 24,346
  • 3
  • 50
  • 88
0

Generally, you should use pass by value when you need to change an argument, and don't want the caller to have to make copies. You should use pass by reference to const pretty much everywhere else.

However, this really comes down to the "C++ as a federation of languages" bit -- for example, if you're writing STL algorithms you need to use pass by value, because iterators and functors approximate pointers and function pointers.

Billy ONeal
  • 104,103
  • 58
  • 317
  • 552
0

It depends ,among other things,largely upon your needs.If you want to see the changes done to passed variable reflected in your current function,surely you will go with pass by reference but if you are strict that any changes to done to the passed variable is not reflected in your current function go for 'passed by value'.

Thanks, Mawia

mawia
  • 9,169
  • 14
  • 48
  • 57