【问题标题】:Explain the code?解释代码?
【发布时间】:2018-07-13 17:00:24
【问题描述】:

我遇到了这段代码。从输出中我可以推断出余数数组在除以 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 在这种情况下做了什么?我阅读了文档,但我不清楚。

【问题讨论】:

  • std::transform,不知道 :bind2nd() 究竟是什么。
  • @πάνταῥεῖ std::bind2nd。在 C++11 中已弃用并在 C++17 中删除。
  • @Miles Cool,可能会解释很多为什么 OP 会询问。
  • 那么可能会有类似bind2Tuple() 的东西作为替代品。
  • 是的,它已被 std::bind 和 lambdas 取代。

标签: c++ bind2nd


【解决方案1】:

std::bind2nd 是一个旧函数,用于将值绑定到函数的第二个参数。它已被 std::bind 和 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 }
}

【讨论】:

    【解决方案2】:

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

    bin2nd(f, x) 假定f 是一个函数(或者至少是可以像函数一样调用的东西),而x 是一个值,可以作为第二个参数传递给该函数。它创建了一些像函数一样的东西。当你调用它创建的函数时,就相当于调用f(something, x),所以它@98​​7654326@x 为其输入函数的第二个参数。

    现在,您可能会这样写:

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

    【讨论】:

      猜你喜欢
      • 2015-03-23
      • 2012-07-20
      • 2010-10-11
      • 2011-09-25
      • 2013-12-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多