为什么我的 std::ref 无法按预期工作?

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

本文关键字:工作 我的 std ref 为什么      更新时间:2023-10-16

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

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

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

在这里玩代码。

#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();
}

这不起作用的原因是您的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();
}

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

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

并且还通过引用return [&]() { 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) {...}