解释代码?

时间:2018-07-13 17:00:25

标签: c++ bind2nd

我遇到了这段代码。从输出中,我可以推断出除数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做什么?我阅读了文档,但对我来说还不清楚。

2 个答案:

答案 0 :(得分:5)

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

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在范围的每个元素上调用一个callable并将调用结果存储到输出范围中。

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 }
}

答案 1 :(得分:3)

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

bin2nd(f, x)假设f是一个函数(或至少可以像函数那样调用的东西),而x是一个值,该值作为第二个值传递给该函数参数。它创建的行为类似于函数。调用它创建的函数时,等效于调用f(something, x),因此将binds x用作其输入函数的第二个参数。

如今,您可能会这样写:

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

关于转换的作用,这很像是一个循环,因此大致相当于:

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数组似乎没有任何用处,只是在打印结果之前保留中间值,所以最好不要创建/填充它。