0

I started learning C++ two days ago and this error I am getting is obscure to me, I am trying to do the following

int sumArray(const int arr)
{
  int sum = 0;
  for (auto &n : arr) {
    sum += n;
  }
  return sum;
};

int main () 
{
  int numbers[] = {1, 2, 5, 10};
  return sumArray(numbers);
}

which is a slight change from an example in "A Tour of C++", the error I am getting is

cpprepl.cpp: In function ‘int sumArray(int)’: cpprepl.cpp:4:18: error: ‘begin’ was not declared in this scope for (auto &n : arr) { ^~~ cpprepl.cpp:4:18: error: ‘end’ was not declared in this scope cpprepl.cpp: In function ‘int main()’: cpprepl.cpp:13:26: error: invalid conversion from ‘int*’ to ‘int’ [-fpermissive] return sumArray(numbers); ^ cpprepl.cpp:1:5: note: initializing argument 1 of ‘int sumArray(int)’ int sumArray(const int arr) ^~~~~~~~

If I do

int main () {
  int arr[] = {1, 2, 5, 10};

  int sum = 0;
  for (auto &n : arr) {
    sum += n;
  }
  return sum;
}

everything is fine, so I suspect I am not understanding pointers and how C++ is passing numbers to sumArray; I've seen multiple questions on similar subjects but I'm still missing how this should be done.

Alberto Zaccagni
  • 28,473
  • 10
  • 71
  • 102
  • s/`int sumArray(const int arr)`/`int sumArray(const int arr[4])` – user0042 Sep 23 '17 at 10:51
  • @user0042 Did that, still getting the first two errors about `begin` and `end`. – Alberto Zaccagni Sep 23 '17 at 10:53
  • I'd recommend you should use a `std::vector` instead of a raw array. – user0042 Sep 23 '17 at 10:54
  • I'm not there yet. BTW: even with your edited answer I still get the error. – Alberto Zaccagni Sep 23 '17 at 10:55
  • You should be. Using the standard C++ library is what's preferred over usage of raw arrays or pointers. The latter stuff is advanced, not vice versa. – user0042 Sep 23 '17 at 10:56
  • @user0042 A parameter `const int arr[4]` has type `const int *`, not `const int [4]`. –  Sep 23 '17 at 10:58
  • I can imagine that, I'm not there yet though. I want to understand what I'm doing wrong, not use a better data structure. – Alberto Zaccagni Sep 23 '17 at 10:58
  • 2
    When passing the array as a parameter, it "decays" to a pointer. Pointers cannot be used with that form of for-statement as there is no way to get the length of the array the pointer *might* be pointing to. – Bo Persson Sep 23 '17 at 11:03
  • Possible duplicate of [What is array decaying?](https://stackoverflow.com/questions/1461432/what-is-array-decaying) – user0042 Sep 23 '17 at 11:05
  • @AlbertoZaccagni It explains the essential problem of your question (besides the silly typo) well though. – user0042 Sep 23 '17 at 11:10
  • @user0042 What you call silly typo is actually me not understanding C++ yet. It might be explaining the problem, but how is a newbie supposed to know what "array decaying" is? – Alberto Zaccagni Sep 23 '17 at 11:12
  • @AlbertoZaccagni _"but how is a newbie supposed to know what "array decaying" is?"_ That's why and how we point them in the right directions. Who ever set up a policy that Stack Overflow needs to be _"newbie friendly"_? – user0042 Sep 23 '17 at 11:14
  • @Alberto - Pointers and passing array parameters are really difficult parts that C++ has inherited from C. That's why you immediately get the recommendation to use a `std::vector` instead. That is C++'s solution to most of those problems. `std::vector arr` just works, both as a declaration and as a parameter. – Bo Persson Sep 23 '17 at 11:19

2 Answers2

4

As mentioned, const int arr doesn't make sense since it's just a single int, not an array, and const int *arr and const int arr[4] mean the same thing and declare arr as a pointer without information about how many ints are pointed to. The error message is just confusing.

To allow keeping track of this without using standard library container types, you can pass the array by reference:

int sumArray(const int (&arr)[4])

To allow arrays of arbitrary length to be passed in, you can make it a function template:

template <int N> int sumArray(const int (&arr)[N])
  • 1
    Passing arrays by reference is underused. – DeiDei Sep 23 '17 at 11:06
  • Ok now I understand why I should not use a raw array, it feels like a lot of work and I don't like to introduce a new thing (the function template, whatever that is :D), I can just use a vector. Thanks! – Alberto Zaccagni Sep 23 '17 at 11:14
2

C++ doesn't support the foreach-style loop for this sort of array, since it doesn't have any size information to construct the underlying iteration. As suggested in the comments, it would be better to just use std::vector.


If the size information would be available, such as in the case where both the array and for are in the same "scope", it might work. See this question for info.

Horia Coman
  • 8,074
  • 2
  • 19
  • 23
  • I saw it was suggested in the comments but without motivation I can't really just accept is as truth :D, thanks for adding the *why*. – Alberto Zaccagni Sep 23 '17 at 11:04
  • 1
    @AlbertoZaccagni that's the case I was referring to in the second paragraph. The compiler knows that `arr` has 4 elements because that's how you've defined it. So it knows how to translate the `foreach`-style loop into a regular `for (i = 0; i < 4; i++)` loop. In the first case it doesn't have that info inside the `sumArray` function, so it can't do anything. Sure, it _could_ look and see that you're calling it with an array of `4` elements, but that would be very burdersome to do generally for large programs. And impossible if you plan on exporting the function from a binary for later use. – Horia Coman Sep 23 '17 at 11:06
  • ah-ha! Got it, thanks! – Alberto Zaccagni Sep 23 '17 at 11:21