我有以下 C++11 代码:
#include <iostream>
#include <functional>
using namespace std;
using namespace placeholders;
void f(int a, int b)
{
cout << a << " " << b << endl;
}
void g(int& a, int& b)
{
a *= 2;
b *= 3;
}
int main()
{
int a = 100;
int b = 200;
auto greversed = bind(g,_2,_1);
greversed(b,a);
f(a,b);
greversed(ref(b),ref(a));
f(a,b);
}
基于我对“C++ 编程语言第 4 版”(Stroustrup)的阅读。 968 我希望在第一次调用 greversed(b,a) 期间,a 和 b 的拷贝将通过引用传递给 g(),并且只有第二次调用实际上会通过引用将 a 和 b 传递给 g() .
p 中给出的示例代码。 968:
void incr(int& i)
{
++i;
}
void user()
{
int i =1;
incr(i); // i becomes 2
auto inc = bind(incr,_1);
inc(i); // i stays 2; inc(i) incremented a local copy of i
}
运行这段代码,i 会增加两次,不管评论怎么说。
对于我的程序,我的预期输出是:
100 200
200 600
但是,当我在 Ubuntu 下使用“g++ -std=c++11 test.cpp”编译此代码时,我得到以下输出:
200 600
400 1800
无论是否使用 ref() 适配器,似乎 a 和 b 都是通过引用传递的。
最佳答案
简介
std::placeholders::_*
通过完美转发后来取代它们的类型来工作。
这意味着由于您将 a 和 b(它们是 lvalues)传递给 greversed 这些 < em>左值将被转发到g
,就像它们一样。
标准 (n3337) 的 [func.bind.bind]p10
部分对此行为进行了说明,但可以在此处找到更易于理解的说明:
困惑的来源
我没有读过你所指的书,但你的困惑可能在于 std::bind
在你使用 std::bind
时不会绑定(bind)对传入参数的引用em>非占位符,而是复制参数。
以下示例希望有助于理解使用 std::placeholder 和传入要绑定(bind)的值之间的区别。
int main () {
auto f = [](int& r1, int& r2) {
r1 *= 2;
r2 *= 2;
};
int a = 1;
int b = 2;
auto x = std::bind (f, a, std::placeholders::_1); // a copy of `a` will be stored
// inside `x`
x (b); // pass the copy of `a`, and perfectly-forward `b`, to `f`
std::cout << "a: " << a << std::endl;
std::cout << "b: " << b << std::endl;
}
a: 1
b: 4
关于c++ - 使用 bind() 时,即使不使用 ref() 适配器,参数也会通过引用传递,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24208582/