我在Visual Studio 2012中使用函数对象时遇到问题。
我创建了一个简单的std::vector
,添加了ints
0-9,并希望使用函数对象创建它的总和。我的班级定义(内联):
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;
}
};
我的主要职能:
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;
}
使用析构函数的输出,我会得到:
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
这是VS的错误吗?使用调试器运行它,这些项目总计为45
,但之后会立即调用析构函数。我做错了什么?
编辑:
这是Stroustrup The C++ Programming Language
第18.4章的一个例子。我只是想知道它没有用,因为我完全复制了它。
答案 0 :(得分:5)
问题是std::for_each
按价值接受您的仿函数参数。这意味着它可以处理原始对象的副本。好消息是它还返回保存修改状态的副本。这应该可以解决问题:
Sum<int> s1 = std::for_each(vec.begin(), vec.end(), s);
std::cout << "Sum of all numbers: " << s1.result() << std::endl;
或者,您可以让您的仿函数中的val
成为某个变量的参考:
template <class T>
class Sum {
private:
T& val;
public:
Sum (T& i) : val(i) {
}
// ...
现在,这应该有效:
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;
但是你必须注意确保i
的生命周期得到充分扩展,不要让Sum<T>::val
成为悬挂参考。