2013-04-15 67 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,稍後的調用將應用於綁定的副本,而不是原始對象。

您可以使用訪問對象的內部狀態,以兩種方式綁定對象,更改原始對象並查看結果如何不同的成員函數來測試此功能。