0

在 c++primer 第 5 版 p393 中写道:

lambda 捕获的变量是局部变量

然后,本书将 显示ostream为引用参数,由 lambda 通过引用捕获。这是相似的:

#include <iostream>
using namespace std;
void foo(ostream &os) {
    auto f = [&os]() { os << "Hellow World !" << endl; //return os;
    };
    f();
}
void main() {
    foo(cout);
    system("pause");
}

我遇到的问题是,这里的 os 不是局部变量foo,它存在于foo的范围之外,但它可以被 lambda 捕获,而“由 lambda 捕获的变量是局部变量”。我在这里想念什么?另外,为什么 lambda 不能return os;?毕竟,不是os存在于 lambda 和foo' 范围之外的对象吗?

4

2 回答 2

3

我挣扎的是,这里os不是一个局部变量foo,它存在于foo's 范围之外,

不,它是本地的,它不存在foo.

被引用的对象os存在于foo, 因为os是一个引用之外。但这在这里无关紧要,因为我们谈论的是变量,而不是对象

另外,为什么 lambda 不能return os;

可以,你只需要指定一个显式的返回类型,否则返回类型被推断为std::ostream,即代码将尝试复制流,并且它是不可复制的。

但以下工作:

auto f = [&os]() -> std::ostream& { return os << "Hellow World !" << endl; };
于 2020-05-01T09:14:59.920 回答
3

上面的 lambda 由编译器编译成类似于foo2()中的f2的东西。所以 lambda 实例在foo2中是本地的,而 ostream 引用(指针)是本地 lambda 实例中的成员变量。

因此,您必须确保带有对 ostream 的包装引用的 lambda 不会超过 ostream (os) 本身,这在这种情况下不会发生,因为 lambda 实例仅存在于函数范围内 -> 比传递的范围更小ostream 引用 os 参数。

#include <iostream>
using namespace std;
void foo(ostream &os) {
    auto f = [&os]() { os << "Hellow World !" << endl; //return os;
    };
    f();
}

void foo2(ostream& os) {
    // The lambda f from foo is compiled to something similar to f2.
    struct f2 {
        f2(ostream& oss)
        : os_(oss) {}

        void operator()() const
        {
            os_ << "Hellow World !" << endl; 
        }

        private:
        ostream& os_; // Note: this is reference, but local to f2 ( == "lambda")
    };

    f2 t(os);
    t(); // call "lambda"
}

int main() {
    foo(cout);
    foo2(cout);
    return 0;
}
于 2020-05-01T09:25:53.377 回答