使用bind()时,即使未使用ref()适配器,也会通过引用传递参数

时间:2014-06-13 15:08:38

标签: c++ c++11

我有以下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都是通过引用传递的。

1 个答案:

答案 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}}