6

I have a broad level question regarding best practices for passing arrays into functions.

So in the past when I've been programming in C and I wanted a function to have it's input be an array, I would declare that functions input parameters to be a pointer. This worked relatively well.

However, I've began programming more in C++ and am trying to determine the best practice for passing arrays into functions. So I've noticed that it is popular in C++ to pass objects by reference such that expensive copying operations are avoided. However, when I google passing arrays into functions, I read statements saying that arrays are automatically passed by reference.... So what's the deal with this? Why are arrays automatically passed by reference? And let's say I don't want the function to modify the array, is it possible to pass const arrays?

I'm having a difficult time getting my test program to compile. So I'm curious if anyone could explain what it means to pass an array into a function in C++ and how that differs from C.

Thanks!

Izzo
  • 4,461
  • 13
  • 45
  • 82
  • 1
    Please elaborate "*This worked relatively well.*"? Also, don't use [tag:c] arrays in [tag:c++], use `std::vector` and yes, pass them by reference whenever makes sense. – Iharob Al Asimi Feb 21 '16 at 03:25
  • Well, things changed a little bit because c++11 added std::array which is deep copy by default. But best practice using c++ especially c++11 and later is not to use c style arrays, and sometimes avoid pointers, too. – user3528438 Feb 21 '16 at 03:32

3 Answers3

16

In both C and C++, declaring a function to take an array parameter, such as in the following example, in fact causes the function to take a pointer. For example:

void foo(int arr[]);

This function signature is identical to:

void foo(int *arr);

Thus when you try to pass an array in either C or C++ you're already avoiding any overhead of copying an array.

Why are arrays automatically passed by reference?

They're passed by reference only in a loose sense. They're not literally passed as a C++ reference, which would look like the following:

void foo(int (&arr)[10]); // arr is a reference to an array of 10 ints

The reason for the C behavior is because they thought passing arrays by value would never be used anyway because of the expensive copy. The reason C++ has the same behavior is simply for compatibility.

Experience has shown that the special behavior of array parameters was a bad idea, and so it is one of the many reason that one should avoid using raw arrays in C++. The problem is that passing an array either way is dangerous:

void foo(int arr[10]) { arr[9] = 0; }

void bar() {
    int data[] = {1, 2};
    foo(data);
}

The above code is wrong but the compiler thinks everything is fine and issues no warning about the buffer overrun.

Instead use std::array or std::vector, which have consistent value semantics and lack any 'special' behavior that produces errors like the above.

And let's say I don't want the function to modify the array, is it possible to pass const arrays?

You can:

void foo(int const arr[]);
void foo(int const *arr);

void foo(int const (&arr)[10]);

So I'm curious if anyone could explain what it means to pass an array into a function in C++ and how that differs from C.

If you use the syntax that works in C then it doesn't really differ at all.

bames53
  • 86,085
  • 15
  • 179
  • 244
1

Best practice in C++ is to not use C-style arrays at all.

In C++, C-style arrays can be passed the same as they were in C. This could be described as passing the contents of the array by reference, because the function can modify the caller's array by indirecting through the pointer passed.

In C++, if you really do want to use C-style arrays, you can choose between passing by pointer (as in C), and passing by using a C++ reference (see here for example).

Community
  • 1
  • 1
M.M
  • 138,810
  • 21
  • 208
  • 365
  • I see... However, I assume passing a C++ array by reference could be difficult because the function would have to be declared to expect an array of a specific size. Correct? – Izzo Feb 21 '16 at 03:53
  • @Teague That's correct, and that also protects against many of the dangers of raw arrays. Passing an actual reference to an array of a specific size should be preferred over the C style of passing an array. If you want to accept arrays of different sizes then you can use a function template. – bames53 Feb 21 '16 at 03:55
  • @Teague You can put the size as a template parameter (which has the slight [code visibility issue for templates](http://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file)) – M.M Feb 21 '16 at 04:03
1

In C++ best practice is to allow your arrays to be managed by containers, either std::array (compile time fixed) or std::vector (runtime variable).

Typically, if you don't want the array modified you will pass by const reference:

void func(const std::vector<int>& v); // pass by const reference

Otherwise, to modify the array in the function pass by normal reference:

void func(std::vector<int>& v); // pass by reference

More sophisticated and generic is to pass iterators to your function so that it can operate upon the entire array or just a part of it.

template<typename Iterator>
void func(Iterator begin, Iterator end);

That will be called like:

func(v.begin(), v.end()); // operate on the whole array

Containers, iterators and algorithms (iterator based processing) have virtually eliminated the need for managing the array yourself.

Galik
  • 47,303
  • 4
  • 80
  • 117