为什么我的 std::ref 没有按预期工作?
Why does my std::ref not work as expected?
std::ref
给你一个 lvalue-reference
的东西。该引用被包装到一个对象中,然后您可以通过引用或值传递该对象。
下面代码的预期行为是它打印i is 2
,但它打印i is 1
。 这是为什么?
为什么我会有这样的期待?因为我正在通过std::ref
传递tmp
到wrapper
。在包装器中,引用然后按值捕获。我会假设,因为我使用的是 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();
}
您需要更改函数签名以接受引用:
auto wrapper(int& i, F func) {...}
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::ref
returns一个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();
}
std::ref
给你一个 lvalue-reference
的东西。该引用被包装到一个对象中,然后您可以通过引用或值传递该对象。
下面代码的预期行为是它打印i is 2
,但它打印i is 1
。 这是为什么?
为什么我会有这样的期待?因为我正在通过std::ref
传递tmp
到wrapper
。在包装器中,引用然后按值捕获。我会假设,因为我使用的是 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();
}
您需要更改函数签名以接受引用:
auto wrapper(int& i, F func) {...}
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::ref
returns一个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();
}