为啥我的 std::ref 不能按预期工作?
Posted
技术标签:
【中文标题】为啥我的 std::ref 不能按预期工作?【英文标题】: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::ref
将tmp
传递给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
的东西。
【参考方案1】:
您需要更改函数签名以接受引用:
auto wrapper(int& i, F func) ...
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) ...
【讨论】:
好吧...但是为什么std::ref
不为我做呢?我认为其中一个要点是引用某些东西,即使我是按值传递
@User12547645 因为您的函数不接受引用或std::reference_wrapper<int>
。他们接受副本。【参考方案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<int>
到int
的隐式转换。但是,是的,听起来合乎逻辑。谢谢!以上是关于为啥我的 std::ref 不能按预期工作?的主要内容,如果未能解决你的问题,请参考以下文章