2013-04-15 192 views
7

的绑定我有这样的代码:的std ::类成员函数

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

是equivalento到:

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

为什么?

+8

它不是。一个绑定一个指针,另一个绑定一个* copy *。 – Xeo

+1

对于它的价值,你也可以传递一个智能指针(任何实现'operator->'来返回'foo *')作为第二个参数的类型。试试用'std :: shared_ptr'。 –

+0

重复:http://stackoverflow.com/questions/15264003/using-stdbind-with-member-function-use-object-pointer-or-not-for-this-argumen 虽然我喜欢这两个答案... – nephewtom

回答

14

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

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

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