【问题标题】:Why does my std::ref not work as expected?为什么我的 std::ref 不能按预期工作?
【发布时间】:2020-06-07 07:08:29
【问题描述】:

std::ref 给你一个lvalue-reference 的东西。此引用被包装到一个对象中,然后您可以通过引用或值传递该对象。

下面代码的预期行为是它打印i is 2,但它打印i is 1为什么会这样?

我为什么会有这种期望?因为我通过std::reftmp 传递给wrapper。然后在包装器中按值捕获引用。我会假设,因为我使用的是std::ref,所以这个值现在仍然是对tmp 的引用。我正在更改 tmp 并希望 f 反映该更改。

Play with the code here.

#include <iostream>
#include <functional>

template<typename F>
auto wrapper(int i, F func) {
    return [=]() { return func(i); };
}

void f(int i) {
    std::cout << "i is " << i << '\n';
}

int main() {
    int tmp = 1;
    auto func = wrapper(std::ref(tmp), f);
    tmp = 2;
    func();
}

【问题讨论】:

  • "std::ref 给你一个lvalue-reference 的东西" - 没有。它会给你std::reference_wrapper 的东西。

标签: c++ reference pass-by-reference higher-order-functions pass-by-value


【解决方案1】:

您需要更改函数签名以接受引用:

  1. auto wrapper(int&amp; i, F func) {...}
  2. void f(int&amp; i) {...}

并且还通过引用 return [&amp;]() { return func(i); }; 进行 lambda 捕获。那你就不需要std::ref了。

完整代码如下:

#include <iostream>
#include <functional>

template<typename F>
auto wrapper(int& i, F func) {
    return [&]() { return func(i); };
}

void f(int& i) {
    std::cout << "i is " << i << '\n';
}

int main() {
    int tmp = 1;
    auto func = wrapper(tmp, f);
    tmp = 2;
    func();
}

现在上面的代码会打印出来:

i is 2

如果您仍想使用std::ref,那么您的模板函数应具有以下签名:

template<typename F>
auto wrapper(std::reference_wrapper<int> i, F func) {...}

【讨论】:

  • 好吧...但是为什么std::ref 不为我做呢?我认为其中一个要点是引用某些东西,即使我是按值传递
  • @User12547645 因为您的函数不接受引用或std::reference_wrapper&lt;int&gt;。他们接受副本。
【解决方案2】:

这不起作用的原因是因为您的 wrapper 函数将 int 作为参数。

std::ref 返回一个std::reference_wrapper。 当您将其传递给需要 int 的函数时 您将获得隐式转换,并且不再使用引用。

如果您将函数签名更改为使用std::reference_wrapper,它将给出预期的结果。

#include <iostream>
#include <functional>

template<typename F>
auto wrapper(std::reference_wrapper<int> i, F func) {
    return [=]() { return func(i); };
}

void f(int i) {
    std::cout << "i is " << i << '\n';
}

int main() {
    int tmp = 1;
    auto func = wrapper(std::ref(tmp), f);
    tmp = 2;
    func();
}

【讨论】:

  • 现在这很有意义!我不知道reference_wrapper&lt;int&gt;int 的隐式转换。但是,是的,听起来合乎逻辑。谢谢!
猜你喜欢
  • 2019-02-14
  • 1970-01-01
  • 2015-07-25
  • 1970-01-01
  • 1970-01-01
  • 2016-09-27
  • 2020-01-10
  • 1970-01-01
  • 2021-05-30
相关资源
最近更新 更多