2

This succeeds:

#include <iostream>
#include <vector>
using namespace std;

int test(vector<int> items)
{
    for (int item : items)
    {
        cout << item;
    }
    return 0;
}

int main()
{
    vector<int> items = { 1, 2, 3 };
    test(items);
    return 0;
}

This fails:

#include <iostream>
using namespace std;

int test(int items[])
{
    for (int item : items)
    {
        cout << item;
    }
    return 0;
}

int main()
{
    int items[] = { 1, 2, 3 };
    test(items);
    return 0;
}

The error message is:

main.cpp: In function ‘int test(int*)’:
main.cpp:14:21: error: ‘begin’ was not declared in this scope
     for (int item : items)
                     ^~~~~
main.cpp:14:21: note: suggested alternatives:
In file included from /usr/include/c++/6/string:51:0,
                 from /usr/include/c++/6/bits/locale_classes.h:40,
                 from /usr/include/c++/6/bits/ios_base.h:41,
                 from /usr/include/c++/6/ios:42,
                 from /usr/include/c++/6/ostream:38,
                 from /usr/include/c++/6/iostream:39,
                 from main.cpp:9:
/usr/include/c++/6/bits/range_access.h:87:5: note:   ‘std::begin’
     begin(_Tp (&__arr)[_Nm])
     ^~~~~
/usr/include/c++/6/bits/range_access.h:87:5: note:   ‘std::begin’
main.cpp:14:21: error: ‘end’ was not declared in this scope
     for (int item : items)
                     ^~~~~
main.cpp:14:21: note: suggested alternatives:
In file included from /usr/include/c++/6/string:51:0,
                 from /usr/include/c++/6/bits/locale_classes.h:40,
                 from /usr/include/c++/6/bits/ios_base.h:41,
                 from /usr/include/c++/6/ios:42,
                 from /usr/include/c++/6/ostream:38,
                 from /usr/include/c++/6/iostream:39,
                 from main.cpp:9:
/usr/include/c++/6/bits/range_access.h:97:5: note:   ‘std::end’
     end(_Tp (&__arr)[_Nm])
     ^~~
/usr/include/c++/6/bits/range_access.h:97:5: note:   ‘std::end’

I found a similar problem, which explained that the program did not know the size of the array. How to fix for each loop in C++?

But when I tested this, it was successful:

#include <iostream>
using namespace std;

int main()
{
    int items[] = { 1, 2, 3 };
    for (int item : items)
    {
        cout << item;
    }
    return 0;
}

Why does this succeed without specifying the size of the array?

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
Erriorn
  • 47
  • 4
  • 2
    In the second example, `items` is a pointer, not an array. In general, it's impossible to make a function with an array parameter, that parameter will be silently replaced with a pointer parameter. – HolyBlackCat Aug 14 '21 at 10:11
  • use `std::array` if you want an array with all bells and whistles added. C arrays are only for legacy code – 463035818_is_not_an_ai Aug 14 '21 at 10:16

3 Answers3

3

Arrays cannot be passed to functions by value. This signature

int test(int items[])

is equivalent to

int test(int* items)

A pointer has no begin nor end and there is no way to deduce the size of the array from the pointer alone. In your second example items in main is an array (remember: arrays are not pointers), and there is std::begin() and std::end() that takes c-arrays by reference, hence the range based loop works.

If you do take the array by reference, also your function will work as expected:

int test(int (&items)[3])   // now items is a reference to an array (not a pointer!)
{
    for (int item : items)
    {
        cout << item;
    }
    return 0;
}

If you make test a template you could even pass arrays of different sizes, but often it is simpler to use std::array.

463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185
  • So when I pass the array in C++, it doesn't copy the array but passes the pointer, and the vector is copy the same data, right? – Erriorn Aug 14 '21 at 12:40
  • @Errion right. `int test(vector items)` takes the vector by copy. You should pass a const reference instead `int test(const vector& items)` to avoid the copy – 463035818_is_not_an_ai Aug 14 '21 at 17:11
1

What is explained in the comments is true:

it's impossible to make a function with an array parameter

because of array to pointer decay, but you can have a function with a reference-to-array parameter:

#include <iostream>
using namespace std;

template<int N>
int test(int (&items)[N]) // what an ugly syntax, isn't it?
{
    for (int item : items)
    {
        cout << item;
    }
    return 0;
}

int main()
{
    int items[] = { 1, 2, 3 };
    test(items);
    return 0;
}

where the use of N as a template parameter is to allow the function taking arrays of any length.

I case you have to support array of only length 3, which I don't think you want to, than you can give up the template parameter:

int test(int (&items)[3])

But honestly, the best suggestion is to stop using C-style arrays all together. Use std::array and std::vector for fixed and variable size arrays respectively.

Enlico
  • 23,259
  • 6
  • 48
  • 102
-1

Try this in the function test :

int test(vector<int> items)

So :

int test(vector<int> items)
{
    for (int item : items)
    {
            cout << item;
    }
  return 0;
}

It returns :

123

Functions and arrays are not compatible. It's hightly recommanded to use vectors in parameter of a function in C++.

Phoboe
  • 21
  • 4