std :: bind类成员函数

时间:2013-04-15 13:14:55

标签: c++ c++11

我有这段代码:

#include <iostream>
#include <functional>

struct Foo
{
        int get(int n) { return 5+n; }
};

int main()
{
        Foo foo;
        auto L = std::bind(&Foo::get, &foo, 3);

        std::cout << L() << std::endl;

        return 0;
}

似乎是这样:

auto L = std::bind(&Foo::get, &foo, 3);

等同于:

auto L = std::bind(&Foo::get, foo, 3);

为什么?

2 个答案:

答案 0 :(得分:15)

std::bind()接受其参数按值。这意味着在第一种情况下,您按值传递指针,从而生成指针的副本。在第二种情况下,您按值传递类型为foo的对象,从而生成类型为Foo的对象的副本。

因此,在第二种情况下,对表达式L()的求值会导致在原始对象{{1}的副本上调用成员函数get()你想要的可能是也可能不是。

这个例子说明了区别(忘记违反三条规则/五条规则,这只是为了说明目的):

foo

Live example

如果出于任何原因,您不想使用指针表单,则可以使用std::ref()来阻止创建参数的副本:

#include <iostream>
#include <functional>

struct Foo
{
    int _x;

    Foo(int x) : _x(x) { }

    Foo(Foo const& f) : _x(f._x)
    {
        std::cout << "Foo(Foo const&)" << std::endl;
    }

    int get(int n) { return _x + n; }
};

int main()
{
   Foo foo1(42);

   std::cout << "=== FIRST CALL ===" << std::endl;
   auto L1 = std::bind(&Foo::get, foo1, 3);
   foo1._x = 1729;
   std::cout << L1() << std::endl; // Prints 45

   Foo foo2(42);

   std::cout << "=== SECOND CALL ===" << std::endl;
   auto L2 = std::bind(&Foo::get, &foo2, 3);
   foo2._x = 1729;
   std::cout << L2() << std::endl; // Prints 1732
}

答案 1 :(得分:4)

他们不一样。通用函数绑定器std::bind 复制它的参数。在std::bind(&Foo::get,&foo,3)的情况下,指针被复制,但是当您调用绑定对象时,它仍然适用于原始foo对象。在std::bind(&Foo::get,foo,3)中复制对象foo,后一个调用应用于绑定副本,而不是原始对象。

您可以使用访问对象内部状态的成员函数,以两种方式绑定对象,更改原始对象以及查看结果的不同来测试这一点。