std::bind()
chấp nhận đối số theo giá trị. Điều này có nghĩa là trong trường hợp đầu tiên bạn chuyển một con trỏ theo giá trị, dẫn đến bản sao của một con trỏ. Trong trường hợp thứ hai, bạn đang truyền một đối tượng kiểu foo
theo giá trị, dẫn đến một bản sao của một đối tượng thuộc loại Foo
.
Do đó, trong trường hợp thứ hai đánh giá của biểu thức L()
làm cho viên chức năng get()
được gọi trên bản sao của đối tượng gốc foo
, mà có thể hoặc không thể là những gì bạn muốn.
Ví dụ này minh họa sự khác biệt (quên vi phạm các Rule của Ba/Rule of Five, điều này chỉ là dành cho mục đích minh hoạ):
#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.
Nếu vì lý do nào đó, bạn không muốn sử dụng mẫu con trỏ, bạn có thể sử dụng std::ref()
để ngăn chặn một bản sao của các đối số từ được tạo ra:
auto L = std::bind(&Foo::get, std::ref(foo), 3);
Nguồn
2013-04-15 13:21:47
Nó không phải. Một liên kết với một con trỏ, cái kia liên kết một bản sao *. – Xeo
Đối với những gì nó có giá trị, bạn cũng có thể vượt qua một con trỏ thông minh (bất kỳ loại nào thực hiện 'toán tử->' để trả về 'foo *') làm đối số thứ hai. Hãy thử nó với một 'std :: shared_ptr'. –
trùng lặp: http: //stackoverflow.com/questions/15264003/using-stdbind-with-member-function-use-object-pointer-or-not-for-this-argumen Mặc dù tôi thích cả hai câu trả lời ... – nephewtom