0

I'm new to C++ and I couldn't find explanation about how to pass an array of objects as a reference. When I pass it regularly, it only updates the values at the scope of unside the function, unlike in C#, where it's automatically passed by reference. Thanks.

Ulrich Eckhardt
  • 16,572
  • 3
  • 28
  • 55
Anton Raskin
  • 133
  • 2
  • 13
  • 1
    https://stackoverflow.com/questions/5724171/passing-an-array-by-reference – Ulrich Eckhardt Jul 19 '15 at 08:48
  • An array like `MyClass xyz[123];` ? Then you´re doing something wrong, because value changes inside the function should be permanent (only the pointer address is copied). – deviantfan Jul 19 '15 at 08:49
  • 1
    Is it a fixed size array or a dynamically sized array? Perhaps it would help to show your code. – Chris Drew Jul 19 '15 at 08:51
  • 1
    Concerning your claim that you "couldn't find explanation about how to pass an array of objects as a reference", you must be doing something wrong: https://duckduckgo.com/?q=C%2B%2B+how+to+pass+an+array+of+objects+as+a+reference&ia=qa – Ulrich Eckhardt Jul 19 '15 at 08:55
  • 1
    @Anton Raskin Could you show a code snippet that demonstrates the problem? From your post it is not clear what problem you have. – Vlad from Moscow Jul 19 '15 at 09:01
  • See http://stackoverflow.com/questions/5724171/passing-an-array-by-reference – juanchopanza Jul 19 '15 at 09:30
  • Also, you don't need to say "object array" in C++. It is no different to "array", because everything you can store in an array in C++ is an object. – juanchopanza Jul 19 '15 at 09:32

3 Answers3

3

If you haven an actual array like e.g.

MyClass array[X];

Then when you pass it to a function is decays to a pointer, so in a way it's already passed by reference. It doesn't matter that the function declares the argument like an array, it's still going to be a pointer.

So the two following function declarations are equivalent:

void my_function(MyClass array[X]);

and

void my_function(MyClass* array);

If you have a dynamically allocated array, like e.g.

MyClass* array = new MyClass[X];

then array already is a pointer and don't need to be passed by reference, unless you want to modify the actual pointer.

And if you have an object of type std::vector or std::array (which I recommend over using pointers or plain arrays) then you use the normal ampersand & to pass it by reference.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • I agree about using `std::array` instead but if you have a fixed size array is it not preferable to pass it by reference? So that you have the size available and can use standard library algorithms. – Chris Drew Jul 19 '15 at 09:06
  • 1
    You can also pass a plain C array by reference. It might be worth mentioning that. – juanchopanza Jul 19 '15 at 09:32
  • @ChrisDrew If you pass a C-style array to a function it's decayed to a pointer without any size-information, even if you declare the argument like an array with size, the size is discarded and all you have is still a pointer. In C++ [there are ways to overcome that though](http://stackoverflow.com/questions/437150/can-someone-explain-this-template-code-that-gives-me-the-size-of-an-array). – Some programmer dude Jul 19 '15 at 10:02
  • 1
    @JoachimPileborg It only decays to pointer if the function parameter is a pointer. If you pass a C-style array to a function with a reference to array parameter, then obviously there's no pointer decay. – juanchopanza Jul 19 '15 at 10:42
3

You can pass a raw array by reference, even if the syntax is somewhat ugly:

#include <iostream>

void ModifyArray(int (&array)[5])
{
    array[4] = 0;
}

int main()
{
    int array[5] = { 1, 2, 3, 4, 5 };

    ModifyArray(array);

    std::cout << array[4] << "\n";
}

Using std::array makes the syntax simpler:

#include <iostream>
#include <array>

void ModifyArray(std::array<int, 5>& array)
{
    array[4] = 0;
}

int main()
{
    std::array<int, 5> array = { 1, 2, 3, 4, 5 };

    ModifyArray(array);

    std::cout << array[4] << "\n";
}

If you try to pass a raw array "directly", then you are really passing a pointer to the first element of the array. This is informally called "decaying". The following apparently works, but there is a caveat:

#include <iostream>

void ModifyArray(int array[5]) // works?
{
    array[4] = 0;
}

int main()
{
    int array[5] = { 1, 2, 3, 4, 5 };

    ModifyArray(array);

    std::cout << array[4] << "\n";
}

The caveat is that the size information of the argument, i.e. the [5] part, is ignored. Because, as we have just established, the function does not take an array but a pointer.

Try the following:

#include <iostream>

void ModifyArray(int array[5]) // works?
{
    array[4] = 0; // problem!
}

int main()
{
    int array[3] = { 1, 2, 3 };

    ModifyArray(array);
}

This program compiles fine but invokes undefined behaviour because you try to access the 5th element of a 3-element array. It's no different than this:

#include <iostream>

void ModifyArray(int* array)
{
    array[4] = 0; // problem!
}

int main()
{
    int array[3] = { 1, 2, 3 };

    ModifyArray(array);
}

When you pass collections of elements around, always use std::vector or std::array by default and consider alternatives if you really you need them.

Christian Hackl
  • 27,051
  • 3
  • 32
  • 62
1

Passing an array by reference is typically unnecessary. When you declare an array parameter to a function, it is the same as declaring the parameter to be a pointer, so you have a level of indirection anyway.

When you pass an object like std::vector or std::array, you can pass it by reference like any old parameter, by putting a & before the parameter name.

Here's an example of passing a vector to a function by reference and observing that the contained values are changed for the caller:

#include <vector>
#include <iostream>

void double_all(std::vector<int>& values) {
  for (int& v: values)
    v += v;
}

int main() {
  std::vector<int> values = {0, 1, 2, 3, 4};
  double_all(values);
  for (int v: values)
    std::cout << v << "\n";
}
ben
  • 1,994
  • 12
  • 20
  • You can't declare a non-reference array parameter to a function. There are various ways to declare a pointer which might mislead you to believe it's an array. – Ulrich Eckhardt Jul 19 '15 at 08:52
  • @UlrichEckhardt, I think the answer makes that clear ("declar[ing] an array ... is the same as ... a pointer"). – avakar Jul 19 '15 at 08:55
  • 2
    But you can make the parameter be a reference to an array. C++ has syntax for that. – juanchopanza Jul 19 '15 at 09:29