views:

367

answers:

10

My teacher in c++ told me that call by reference should only be used if I'm not going to change anything on the arrays inside the function. I have some really big vectors that I'm passing around in my program. All the vectors will be modified inside the functions. My matrices are of sizes about [256*256][256][50]...

Is there some particular reason not to use call-by reference here?

AFAIK call by reference should be way faster and consume less memory?

+5  A: 

My teacher in c++ told me that call by reference should only be used if I'm not going to change anything on the arrays inside the function.

It should be used when you are not changing something inside the function or you change things and want the changes to be reflected to the original array or don't care about the changes to be reflected in the original array.

It shouldn't be used if you don't want your function to change your original array (you need to preserve the original values after the call) and the callee function changes the values of the passed argument.

Mehrdad Afshari
It absolutely should be used with larger arrays, even if you don't want to change it. At that point you pass it by const reference and the compiler will keep you honest.
Xorlev
@Xorlev: Yeah. Did I say something else? I'm reading my answer but I can't quite get which part might get misinterpreted. It's saying the same thing.
Mehrdad Afshari
+1  A: 

Usually, in introductory courses, they tell you that so you don't accidentally change something you didn't want to.

Like if you passed in userName by reference, and accidentally changed it to mrsbuxley that probably would cause errors, or at the very least be confusing later on.

taylonr
+3  A: 

Your teacher is wrong. If you need to modify arrays, pass by reference is the way to go. If you don't want something modified, pass by const reference.

Richard Pennington
Actually, maybe "wrong" is too harsh. Perhaps "misunderstood" is better.
Richard Pennington
+1  A: 

I don't see any reason why you can't pass by reference. Alternatively you could pass pointers around, but I think pass by reference is better sometimes as it avoids null pointer exceptions.

If your teacher has suggested this as some kind of convention, then feel free to break it if it makes sense to. You can always document this in a comment above the function.

bramp
+1  A: 

To prevent accidental changes, use pass-by-const-reference; that way, by default*, the passed-in array can't get changed by the called function.

* Can be overridden with const_cast.

Chris Jester-Young
+2  A: 

You can pass by reference if:

  1. you won't modify passed object
  2. you want to modify object and don't want to keep old object untouched

When you pass something by reference, then only pointer is passed to function. If you pass whole object then you need to copy it, so it will consume more cpu and memory.

klew
+1  A: 

Hold on a second.. I'm scared at how people are answering this one. Arrays, as far as I remember, are always passed by reference.

void function(int array[])
{
    std::cout << array[0] << '\n';
}

// somewhere else..
int array[2] = { 1, 2 };
function(array); // No copy happens here; it is passed by reference

Further, you can't say the array argument is a reference explicitly, as that would be the syntax for creating an array of references (something that's not allowed).

void function(int &array[]) // error here
{ /* ... */ }

So what do you mean?

Further, many are saying that you should only do that if you modify the contents of the array inside the function. Then, what about reference-to-const?

void function(const int arr[])
{
    std::cout << arr[0] << '\n';
}

-- edit

Will somebody please point me out how to not pass an array by reference in C++?

-- edit

Oh, so you're talking about vectors. Okay, then the rules of thumb are:

  • Pass by reference only when you want to modify the contents of the vector.
  • Pass by reference-to-const whenever you can.
  • Pass by value only when the object in question is really, really small (like a struct containing an integer, for example), or when it makes sense to (can't think of a case out of the top of my head).

Did I miss something?

-- edit

  • In the case of plain C arrays, it's a good idea to pass them by reference (like in void function(int (&array)[100])) when you want to ensure that the array has a given definite size.

Thanks, dribeas.

n2liquid
this confusion is probably coming from my question as I talk about arrays but I actually mean vectors...
mrbuxley
David Rodríguez - dribeas
+1  A: 

Generally speaking, objects should always be passed by reference. Otherwise a copy of the object will be generated and if the object is substantially big, this will affect performance.

Now if the method or function you are calling does not modify the object, it is a good idea to declare the function as follows:

void some_function(const some_object& o);

This will generate a compile error if you attempt to modify the object's state inside the function body.

Also it should be noted that arrays are always passed by reference.

Austin
+6  A: 

Besides all common discussions on when and how to pass by possibly const reference for non-primitive types, arrays are quite special here.

Due to backwards compatibility with C, and there due to your specific problem: arrays can be huge, arrays are never really passed by value in either C or C++. The array will decay into a pointer to the first element, so when you write:

void foo( type array[100] );

The compiler is actually processing:

void foo( type *array );

Regardless of what the size of the array is (two common pitfalls there: trusting that array is an array inside foo and believing that it will be guaranteed to be 100 elements on it.

Now, in C++ you can actually pass arrays by reference, but the reference must be of the concrete type of the array, that includes the size:

void foo_array( type (&array)[100] );

The funny syntax there is telling the compiler that the function will take an array of exactly 100 elements of type type. The advantage there is that the compiler can perform size checking for you:

// assuming 'type' is defined
int main() {
   type array0[99];
   type array1[100];

   foo( array0 );     // compiles, but if size=100 is assumed it will probably break
                      // equivalent to: foo( &array0[0] )
   // foo2( array0 ); // will not compile, size is not 100
   foo2( array1 );    // compiles, size is guaranteed to be 100
}

Now, the problem is that your function will only work for an array of exactly 100 elements, and in some cases, you might want to perform the same operation in different array sizes. The two solutions are: template the function in the size of the array which will provide a size-safe implementation for each used size --greater compile time and binary size, the template is compiled for every different size-- or using the pass-by-value syntax, which will make the array decay --not safe in size, that must be passed as extra argument, lesser compile time and binary size.

Now, pass-by-reference is very rarely used with arrays.

David Rodríguez - dribeas
Very, very useful answer, at least to me. I always wondered how to create size-safe arrays like that. Cool! (+1, obviously)
n2liquid
A: 

Our house style is to NEVER pass an object by value but to always pass a reference or const reference. Not only do we have data structures that can contain 100s of MB of data and pass by value would be an application killer, but also if we were passing 3D points and vectors by value the our applications would grind to a halt.

lilburne