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

问题描述 投票:1回答:2

std::ref为您提供了lvalue-reference。该引用被包装到一个对象中,然后您可以通过引用或值来传递它。

以下代码的

预期行为是它打印i is 2,但是它打印i is 1为什么呢?

为什么会有这个期望?因为我正在通过tmpstd::ref传递给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();
}
c++ reference pass-by-reference higher-order-functions pass-by-value
2个回答
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();
}

1
投票

您需要更改功能签名以接受引用:

  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) {...}
© www.soinside.com 2019 - 2024. All rights reserved.