rajh2504
rajh2504

Reputation: 1266

C++ for_each() and the function pointer

I am try to make the myFunction give me a sum of the values in the array, but I know I can not use a return value, and when I run my program with the code as so all I get is a print out of the values and no sum why is that?

void myFunction (int i) {
int total = 0;
total += i;
cout << total;
}


int main() {
int array[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

for_each( array, array+10, myFunction);


return 0;
}

Upvotes: 0

Views: 1529

Answers (8)

Kevin Vermeer
Kevin Vermeer

Reputation: 2842

You reset the value of 'total' to 0 each time you call the function.

Declare it 'static'

void myFunction (int i) {
    static int total = 0;
    total += i;
    cout << total;
}

EDIT:

Alternatively, if you want to access the value of 'total' later, you will need to either use a global variable (of some kind! Could be in a class or functor! don't flame me!), or just use a for loop, and pass it in as a pointer (i.e., not use for_each):

void myFunction (int i, int * p_total) {
    //No initialization
    *p_total += i;
    cout << *p_total;
}


int main() {
    int array[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
    int total = 0;

    for(int i = 0; i < 10, i++)
       myFunction(array[i], &total);

    //total is now 55

    return 0;
}

Note: I'm a C programmer trying to learn C++. This is how I would do it (which is very C-like), it might not be the standard C++ way.

Upvotes: 0

Steve M
Steve M

Reputation: 8516

total is a variable with automatic storage duration. Every time myFunction() is called, a new total is created and initialized to 0. You could:

  • give total static storage duration (with the static keyword), but you won't be able to assign its value to anything, because it is still local scope. A bad idea if you want to reuse this function, anyhow.
  • make total a global variable. Also a bad idea if you want to reuse this function
  • make a "functor", as described in Martin York's answer. This is the most reusable implementation

But, my chosen solution is "you're asking the wrong question" and you should be using std::accumulate():

#include <iostream>
#include <numeric>

int main() {
  int array[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

  int total = std::accumulate(array, array+10, 0);
  std::cout << total << '\n';
  return 0;
}

Upvotes: 1

kennytm
kennytm

Reputation: 523214

The total is a local variable. It will be destroyed once the myFunction finished processing one data.

The typical way to have a state is to make myFunction a function object (a struct that overloads the () operator).
The dirty way is to make total a global variable.
In your case I'd recommend you use the accumulate function instead (assuming that cout << total is just for debugging).

Upvotes: 0

Jerry Coffin
Jerry Coffin

Reputation: 490098

You need to make the total persistent across function calls. You also need to access the result separately from adding the intermediate results to it, which rules out (at least straightforward use of) a function at all -- you really need a class instead.

Upvotes: 0

Jonathan Grynspan
Jonathan Grynspan

Reputation: 43472

When you declare a variable (i.e. int total) it exists for the duration of its scope (usually equivalent to the nearest surrounding pair of { and }. So, in your function myFunction, total ceases to exist when the function returns. It returns once per call--once per element in your array, that is. In order to actually sum its values (or otherwise preserve a variable beyond the end of myFunction, you must give it a broader scope.

There are two relevant ways to do this. One is a "good" way, and one is an "easier-but-badly-styled" way. The good way involves a functor or context object--@Martin has already posted an example. The "bad" way is marking int total as static. It'll work the first time you use it, if your code is single-threaded... and then never again. If somebody suggests it... don't do it. :)

Upvotes: 1

Wyatt Anderson
Wyatt Anderson

Reputation: 9893

myFunction is being called each time and total is local to the function... try marking total as static instead:

static int total = 0

Upvotes: 0

Loki Astari
Loki Astari

Reputation: 264361

You really need a functor to store state between iterations:

struct Sum
{
    Sum(int& v):  value(v) {}
    void operator()(int data) const { value += data;}

    int& value;
};

int main()
{
    int array[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

    int total = 0;
    std::for_each( array, array+10, Sum(total));

    std::cout << total << std::endl;
}

Upvotes: 8

Vlad
Vlad

Reputation: 35584

Your total is local at each function call. It's initialized with 0 at every iteration. You could just declare it global (or pack into a parameter, etc.)

Upvotes: 0

Related Questions