//example
void f(int &n1, int& n2)
{
n1++;
n2++;
}
int main()
{
int n1 = 1, n2 = 2;
auto bound1 = std::bind(&f, n1, std::ref(n2));
bound1(); // 1 3
std::cout << n1 << n2 << endl;
auto bound2 = std::bind(&f, std::placeholders::_1, std::ref(n2)); // 2 4
bound2(n1);
std::cout << n1 << n2 << endl;
}
我的第一个问题是关于在函数 f
错了吗?std::bind
在一个通过引用接收参数的函数上?
因为在上面的代码中 n1
并没有改变。毕竟我看到如果我把 std::placeHolders::_1
价值 n1
会有变化。这是我的第二个问题 std::placeHolders
召唤 std::ref
?
我知道这个标题并没有什么提示性...
在一个通过引用接收参数的函数上使用std::bind是错误的吗?
它是合法的......但正如你所指出的那样 n1
是不变的,这可能是令人惊讶的。
用lambda IMO更容易发现差异。
[n1, &n2](){ f(n1, n2); }
与 [&n1, &n2](){ f(n1, n2); }
这是我的第二个问题 std::placeHolders 调用 std::ref?
不是,但是 bind
既要处理 placeholder
类型和 reference_wrapper
特别是类型。
在一个通过引用接收参数的函数上使用 std::bind 是错误的吗?
不,这并没有错。
绑定的参数总是通过值来存储。因此,如果你想让绑定参数引用一个外部对象,就必须使用引用包装器。
这是我的第二个问题std::placeHolders调用std::ref ?
传递给绑定函数的参数都是直接转发的,而没有被值存储。因此,不需要引用包装器。
就像你说的那样。
除非你使用 std::ref
std::cref
或a std::placeholder
,你的参数被复制了。
在调用过程中,"存储 "的参数会通过引用传递给函数,但这不会影响你在调用时传递的对象。
这可能会让人感到惊讶;你只需要习惯它。
你可以从标准的措辞(在 [func.bind.bind]
)但老实说,这一整节都很玄乎。
同样的情况也发生在 std::thread
- 你必须使用 std::ref
如果你想一直带着引用。
这两种 std::thread
和 std::bind
通常 "稍后 "执行引用到的函数,即在当前作用域外执行(您的例子中的 std::bind
是不寻常的;你通常会直接调用 f
直接在那里),所以更安全的是,你必须让它 明确 说:"如果你想要这个东西,就拿这个东西做参考。这可能是设计者的理由,也可能不是。