为什么我的 std::ref 没有按预期工作?

Why does my std::ref not work as expected?

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

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

为什么我会有这样的期待?因为我正在通过std::ref传递tmpwrapper。在包装器中,引用然后按值捕获。我会假设,因为我使用的是 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();
}

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

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

并通过引用进行 lambda 捕获 return [&]() { return func(i); };。那你就不需要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) {...}

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

std::refreturns一个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();
}