C++ std::bind 类成员函数

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16016112/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 20:00:12  来源:igfitidea点击:

std::bind of class member function

c++c++11

提问by Gian Lorenzo Meocci

I have this code:

我有这个代码:

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

Seems that this:

似乎是这样的:

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

is equivalento to:

相当于:

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

Why?

为什么?

回答by Andy Prowl

std::bind()accepts its arguments by value. This means that in the first case you are passing a pointerby value, resulting in the copy of a pointer. In the second case, you are passing an object of type fooby value, resulting in a copy of an object of type Foo.

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

As a consequence, in the second case the evaluation of the expression L()causes the member function get()to be invoked on a copyof the original object foo, which may or may not be what you want.

因此,在第二种情况下,表达式的计算L()会导致在原始 objectget()副本上调用成员函数foo,这可能是也可能不是您想要的。

This example illustrates the difference (forget the violation of the Rule of Three/Rule of Five, this is just for illustration purposes):

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

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

活生生的例子

If, for any reason, you don't want to use the pointer form, you can use std::ref()to prevent a copy of the argument from being created:

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

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

回答by David Rodríguez - dribeas

They are not the same. The generic function binder std::bindcopiesit's arguments. In the case of std::bind(&Foo::get,&foo,3), the pointeris copied, but when you call the bound object it still applies to the original fooobject. In std::bind(&Foo::get,foo,3)the object foois copied, and the later call applies to the bound copy, not to the original object.

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

You can test this by using a member function that accesses internal state of the object, bind the object in both ways, change the original object and see how the results differ.

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