I am having trouble using function-objects in Visual Studio 2012.
I created a simple std::vector
, added the ints
0-9 and wanted to create the sum of it using a function object. My class definition (inline):
template <class T>
class Sum {
private:
T val;
public:
Sum (T i = 0) : val(i) {
}
void operator()(T x) {
val += x;
}
T result() const {
return val;
}
~Sum() {
std::cout << "Invoked destructor! val: " << val << " for this: " << this << std::endl;
}
};
My main function:
int main(int argc, char *argv[]){
Sum<int> s;
int contents[] = {1,2,3,4,5,6,7,8,9};
std::vector<int> vec = std::vector<int>(contents, contents + 9);
std::for_each(vec.begin(), vec.end(), s);
std::cout << "Sum of all numbers: " << s.result() << std::endl;
return 0;
}
Using the output from the destructor, I'll get:
Invoked destructor! val: 45 for this: 003BFDA4
Invoked destructor! val: 45 for this: 003BFDE0
Sum of all numbers: 0
Invoked destructor! val: 0 for this: 003BFEFC
Is this a bug from VS? Running through it using the debugger, the items are summed up to 45
but immediately afterwards the destructor is called. What am I doing wrong?
EDIT:
This is an example from Stroustrup's The C++ Programming Language
, chapter 18.4. I just wondered it didn't work, as I copied it exactly.
The problem is that std::for_each
accepts your functor argument by value. This means it works on a copy of your original object. The good news is that it also returns that copy which holds the modified state. This should do the trick:
Sum<int> s1 = std::for_each(vec.begin(), vec.end(), s);
std::cout << "Sum of all numbers: " << s1.result() << std::endl;
Alternatively, you could let the val
in your functor be a reference to some variable:
template <class T>
class Sum {
private:
T& val;
public:
Sum (T& i) : val(i) {
}
// ...
Now, this should work:
int i = 0;
Sum<int> s(i);
std::for_each(vec.begin(), vec.end(), s);
std::cout << "Sum of all numbers: " << s1.result() << std::endl;
But you will have to take care of making sure that the lifetime of i
is sufficiently extended not to make Sum<T>::val
a dangling reference.