-2

我遇到了这段代码。从输出中我可以推断出余数数组在除以 2 时存储数字数组的余数。但是我不熟悉语法。

#include <iostream>
#include <functional>
#include <algorithm>

using namespace std;

int main ( )
{

    int numbers[ ] = {1, 2, 3};

    int remainders[3];

    transform ( numbers, numbers + 3, remainders, bind2nd(modulus<int>( ), 2) );

    for (int i = 0; i < 3; i++)
    {
        cout << (remainders[i] == 1 ? "odd" : "even") << "\n";
    }
    return 0;

}

在这种情况下 transform 和 bind2nd 做了什么?我阅读了文档,但我不清楚。

4

2 回答 2

5

std::bind2nd是一个旧函数,用于将值绑定到函数的第二个参数。它已被std::bindand lambdas 取代。

std::bind2nd返回一个可调用对象,该对象接受一个参数并以该参数作为其第一个参数并将绑定参数作为其第二个参数来调用包装的可调用对象:

int foo(int a, int b)
{
    std::cout << a << ' ' << b;
}

int main()
{
    auto bound = std::bind2nd(foo, 42);
    bound(10); // prints "10 42"
}

std::bind2nd(及其合作伙伴std::bind1st)在 C++11 中被弃用并在 C++17 中被删除。它们在 C++11 中被更灵活std::bind的 lambda 表达式取代:

int foo(int a, int b)
{
    std::cout << a << ' ' << b;
}

int main()
{
    auto bound = std::bind(foo, std::placeholders::_1, 42);
    bound(10); // prints "10 42", just like the std::bind2nd example above

    auto lambda = [](int a) { foo(a, 42); };
    lambda(10); // prints "10 42", same as the other examples
}

std::transform对范围的每个元素调用一个可调用对象,并将调用结果存储到输出范围中。

int doubleIt(int i)
{
    return i * 2;
}

int main()
{
    int numbers[] = { 1, 2, 3 };
    int doubled[3];

    std::transform(numbers, numbers + 3, doubled, doubleIt);
    // doubled now contains { 2, 4, 6 }
}
于 2018-07-13T17:20:19.243 回答
3

std::bind2nd来自 C++98/03(特别是 pre-lambdas)。

bin2nd(f, x)假设 thatf是一个函数(或者至少是可以像函数一样调用的东西)并且x是一个值,它作为它的第二个参数传递给该函数。它创建了一些像函数一样的东西。当你调用它创建的函数时,它相当于调用f(something, x),所以它bindsx 到它的输入函数的第二个参数。

如今,您可能会写得更像:

transform(std::begin(numbers), std::end(numbers), 
          remainders, 
          [](int x) { return x % 2; });

至于 transform 的作用,它很像一个循环,所以这大致相当于:

for (int i=0; i<3; i++)
    remainders[i] = numbers[i] % 2;

总的来说,我认为原始代码有点半生不熟。在我看来,它可能是在所有这些东西都是相当新的(或者至少对作者来说是新的)时写的。如果我要整体完成这项工作,我可能会将这些操作“折叠”在一起:

std::transform(std::begin(numbers), std::end(numbers),
            std::ostream_iterator<std::string>(std::cout, "\n"), 
            [](int i) { return std::to_string(i) + (i % 2 == 0 ? " is even" : " is odd"); });

除了在打印出结果之前保存一个中间值之外,原始数组似乎没有任何用处remainders,所以最好不要创建/填充它。

于 2018-07-13T17:16:52.680 回答