在std::bind中引用是无用的?

问题描述 投票:0回答:2
//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 ?

我知道这个标题并没有什么提示性...

c++ c++11 c++14 bind placeholder
2个回答
2
投票

在一个通过引用接收参数的函数上使用std::bind是错误的吗?

它是合法的......但正如你所指出的那样 n1 是不变的,这可能是令人惊讶的。

用lambda IMO更容易发现差异。

[n1, &n2](){ f(n1, n2); }[&n1, &n2](){ f(n1, n2); }

这是我的第二个问题 std::placeHolders 调用 std::ref?

不是,但是 bind 既要处理 placeholder 类型和 reference_wrapper 特别是类型。


2
投票

在一个通过引用接收参数的函数上使用 std::bind 是错误的吗?

不,这并没有错。

绑定的参数总是通过值来存储。因此,如果你想让绑定参数引用一个外部对象,就必须使用引用包装器。

这是我的第二个问题std::placeHolders调用std::ref ?

传递给绑定函数的参数都是直接转发的,而没有被值存储。因此,不需要引用包装器。


0
投票

就像你说的那样。

除非你使用 std::refstd::cref或a std::placeholder,你的参数被复制了。

在调用过程中,"存储 "的参数会通过引用传递给函数,但这不会影响你在调用时传递的对象。

这可能会让人感到惊讶;你只需要习惯它。

你可以从标准的措辞([func.bind.bind])但老实说,这一整节都很玄乎。

同样的情况也发生在 std::thread - 你必须使用 std::ref 如果你想一直带着引用。

这两种 std::threadstd::bind 通常 "稍后 "执行引用到的函数,即在当前作用域外执行(您的例子中的 std::bind 是不寻常的;你通常会直接调用 f 直接在那里),所以更安全的是,你必须让它 明确 说:"如果你想要这个东西,就拿这个东西做参考。这可能是设计者的理由,也可能不是。

© www.soinside.com 2019 - 2024. All rights reserved.