我有以下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);
}
基于我阅读&#34; C ++编程语言第4版&#34; (Stroustrup)p。 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
}
运行此代码,无论评论如何,我都会增加两次。
对于我的程序,我的预期输出是:
100 200
200 600
然而,当我使用&#34; g ++ -std = c ++ 11 test.cpp&#34;在Ubuntu下编译此代码时。我得到以下输出:
200 600
400 1800
无论是否使用ref()适配器,似乎a和b都是通过引用传递的。
答案 0 :(得分:19)
std::placeholders::_*
通过完美转发后来取代它们的类型。
这意味着,因为您将 a 和 b ( lvalues )传递给 greversed 这些< em> lvalues 将转发到g
,就像它们一样。
标准[func.bind.bind]p10
)的std::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
不会绑定对传入参数的引用这一事实占位符,而不是复制参数。
以下示例有助于理解使用 std :: placeholder 和传入要绑定的值之间的区别。
{{1}}
{{1}}