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

标签 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);
}

基于我对“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::_* 通过完美转发后来取代它们的类型来工作。

这意味着由于您将 ab(它们是 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/

相关文章:

C++0x |为什么 std::atomic 使用 volatile-qualifier 重载每个方法?

java - 艾略特波浪计算器,图表模式识别

c++ - 可以内联 std::function 还是我应该使用不同的方法?

c++ - 在字符串中使用变量

c++ - g++ 9.1 更新后 std::stable_sort 的问题

c++ - 有没有一种方法可以基于当前类中的可用重载来进行 SFINAE?

c++11 - C++11中的并发阻塞队列

c++ - 没有匹配函数调用 'currency::currency()'

c++ - 将文件数据复制到 int 数组中

c++ - 如何让编译器为我推断出正确的模板整数