在 for_each 上使用函子

发布于 2024-10-21 15:35:44 字数 382 浏览 5 评论 0原文

为什么函子上的 for_each 调用最后没有更新 sum::total

struct sum
{
    sum():total(0){};
    int total;

    void operator()(int element) 
    { 
       total+=element; 
    }
};

int main()
{
    sum s;

    int arr[] = {0, 1, 2, 3, 4, 5};
    std::for_each(arr, arr+6, s);
    cout << s.total << endl; // prints total = 0;
}

Why does the for_each call on functor doesn't update sum::total at the end?

struct sum
{
    sum():total(0){};
    int total;

    void operator()(int element) 
    { 
       total+=element; 
    }
};

int main()
{
    sum s;

    int arr[] = {0, 1, 2, 3, 4, 5};
    std::for_each(arr, arr+6, s);
    cout << s.total << endl; // prints total = 0;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

南薇 2024-10-28 15:35:44

for_each 按值获取函子 - 因此它被复制。例如,您可以使用一个用指向外部 int 的指针初始化的函子。

struct sum
{
    sum(int * t):total(t){};
    int * total;

    void operator()(int element)
    {
       *total+=element;
    }
};

int main()
{
    int total = 0;
    sum s(&total);

    int arr[] = {0, 1, 2, 3, 4, 5};
    std::for_each(arr, arr+6, s);
    cout << total << endl; // prints total = 15;
}

或者您可以使用 for_each 的返回值

struct sum
{
    sum():total(0){};
    int total;

    void operator()(int element) 
    { 
       total+=element; 
    }
};

int main()
{
    sum s;

    int arr[] = {0, 1, 2, 3, 4, 5};
    s = std::for_each(arr, arr+6, s);
    cout << s.total << endl; // prints total = 15;
}

for_each takes the functor by value - so it is copied. You can e.g. use a functor which is initialized with a pointer to an external int.

struct sum
{
    sum(int * t):total(t){};
    int * total;

    void operator()(int element)
    {
       *total+=element;
    }
};

int main()
{
    int total = 0;
    sum s(&total);

    int arr[] = {0, 1, 2, 3, 4, 5};
    std::for_each(arr, arr+6, s);
    cout << total << endl; // prints total = 15;
}

Or you can use the return value from for_each

struct sum
{
    sum():total(0){};
    int total;

    void operator()(int element) 
    { 
       total+=element; 
    }
};

int main()
{
    sum s;

    int arr[] = {0, 1, 2, 3, 4, 5};
    s = std::for_each(arr, arr+6, s);
    cout << s.total << endl; // prints total = 15;
}
蹲墙角沉默 2024-10-28 15:35:44

for_each 按值接收函子的副本。即使在那之后,它也可以自由复制它,但会返回一个副本。

OTOH,您只是想重新发明 std::accumulate ,这会更轻松地完成这项工作:

int total = std::accumulate(arr, arr+6, 0);
cout << total << endl; 

for_each receives a copy of your functor by value. Even after that, it's free to copy it, but does return a copy.

OTOH, you're simply trying to re-invent std::accumulate, which will do the job much more easily:

int total = std::accumulate(arr, arr+6, 0);
cout << total << endl; 
沒落の蓅哖 2024-10-28 15:35:44

因为您传递给 for_eachs 是按值传递的。 for_each 按值接受它!

在 C++0x 中,您可以使用 for_each 解决此问题,

int sum  = 0;
std::for_each(arr, arr+6, [&](int n){ sum += n; });
std::cout << sum ;

输出:

15

IDEONE 上的演示:http ://ideone.com/s7OOn


或者您可以简单地在 std::cout 本身中编写:

std::cout<<std::for_each(arr,arr+6,[&](int n)->int{sum += n;return sum;})(0);

Run : http://ideone.com/7Hyla

请注意,这种不同的语法对于学习目的是可以的,例如 std::for_each 如何工作以及它返回什么,但是我不会在实际代码中推荐这种语法。 :-)


在 C++ 中,您可以在仿函数中编写用户定义的转换函数,

struct add
{
    int total;
    add():total(0){};
    void operator()(int element)  {  total+=element;  }
    operator int() { return total ; }
};

int main()
{
    int arr[] = {0, 1, 2, 3, 4, 5};
    int sum = std::for_each(arr, arr+6, add());
    std::cout << sum;
}

它与 Erik 第二个解决方案的版本略有不同: http ://ideone.com/vKnmA

Because the s which you pass to the for_each is by value. for_each accepts it by value!

In C++0x, you can solve this problem with for_each as,

int sum  = 0;
std::for_each(arr, arr+6, [&](int n){ sum += n; });
std::cout << sum ;

Output:

15

Demo at ideone : http://ideone.com/s7OOn


Or you can simple write in the std::cout itself:

std::cout<<std::for_each(arr,arr+6,[&](int n)->int{sum += n;return sum;})(0);

Run : http://ideone.com/7Hyla

Note such different syntax is okay for learning purpose, as to how std::for_each works, and what it returns, but I would not recommend this syntax in real code. :-)


In C++, you can write user-defined conversion function in the functor as,

struct add
{
    int total;
    add():total(0){};
    void operator()(int element)  {  total+=element;  }
    operator int() { return total ; }
};

int main()
{
    int arr[] = {0, 1, 2, 3, 4, 5};
    int sum = std::for_each(arr, arr+6, add());
    std::cout << sum;
}

It's slightly different version from Erik second solution : http://ideone.com/vKnmA

空城之時有危險 2024-10-28 15:35:44

发生这种情况是因为 std::for_each 要求函子按值传递。
针对您的解决方案的解决方法:

struct sum
{
    sum():total(0){};
    int total;
    sum(sum & temp)
    {
        total = temp.total;
    }
    void operator()(int element) 
    { 
       total+=element; 
    }
};

int main()
{
    sum s;

    int arr[] = {0, 1, 2, 3, 4, 5};
    s = std::for_each(arr, arr+6, s);  // result of for_each assigned back to s
    cout << s.total << endl; // prints total = 0;
}

This happens due to std::for_each requires the functor to be passed by value .
A workaround for your solution:

struct sum
{
    sum():total(0){};
    int total;
    sum(sum & temp)
    {
        total = temp.total;
    }
    void operator()(int element) 
    { 
       total+=element; 
    }
};

int main()
{
    sum s;

    int arr[] = {0, 1, 2, 3, 4, 5};
    s = std::for_each(arr, arr+6, s);  // result of for_each assigned back to s
    cout << s.total << endl; // prints total = 0;
}
べ映画 2024-10-28 15:35:44

如果您希望对象状态在 std::for_each 之后更新,std::ref() 也是另一个选择

struct Sum
{
    int total = 0;
    void operator()(int i) { total += i; }
};

int main()
{
    int arr[] = { 0, 1, 2, 3, 4, 5 };

    Sum obj1;
    Sum t1 = std::for_each(arr, arr + 6, obj1);  // t1.total = 15 
                            // (Note: obj1.total = 0 bcos it is passed by value)

    Sum obj2;
    std::for_each(arr, arr + 6, std::ref(obj2)); // obj2.total = 15 (NO copy)

    Sum t2 = std::for_each(arr, arr + 6, Sum()); // t2.total = 15
}

std::ref() is also another option if you want your object state gets updated after std::for_each

struct Sum
{
    int total = 0;
    void operator()(int i) { total += i; }
};

int main()
{
    int arr[] = { 0, 1, 2, 3, 4, 5 };

    Sum obj1;
    Sum t1 = std::for_each(arr, arr + 6, obj1);  // t1.total = 15 
                            // (Note: obj1.total = 0 bcos it is passed by value)

    Sum obj2;
    std::for_each(arr, arr + 6, std::ref(obj2)); // obj2.total = 15 (NO copy)

    Sum t2 = std::for_each(arr, arr + 6, Sum()); // t2.total = 15
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文