【问题标题】:std::bind of class member function类成员函数的 std::bind
【发布时间】:2013-04-15 13:14:55
【问题描述】:

我有这个代码:

#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);

为什么?

【问题讨论】:

  • 不是。一个绑定一个指针,另一个绑定一个copy
  • 对于它的价值,您还可以传递一个智能指针(实现operator-&gt; 以返回foo* 的任何类型)作为第二个参数。试试std::shared_ptr
  • 重复:stackoverflow.com/questions/15264003/… 虽然我喜欢这两个答案...

标签: c++ c++11


【解决方案1】:

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

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

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

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

Live example.

如果出于任何原因不想使用指针形式,可以使用std::ref() 来防止创建参数的副本:

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

【讨论】:

    【解决方案2】:

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

    您可以使用访问对象内部状态的成员函数对此进行测试,以两种方式绑定对象,更改原始对象并查看结果有何不同。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-01-09
      • 2021-04-27
      • 2019-12-02
      • 2013-01-08
      • 1970-01-01
      相关资源
      最近更新 更多