Это ссылка на локальную переменную

В C++primer 5th edition p393 написано:

Переменные, захваченные лямбдой, являются локальными переменными

Затем книга показывает ostreamв качестве параметра, на который указывает ссылка, который фиксируется лямбда-функцией по ссылке. Это похоже:

#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область видимости, но это может быть захвачено лямбдой, в то время как "переменные, захваченные лямбдой, являются локальными переменными". Что мне здесь не хватает? Кроме того, почему лямбда не можетreturn os;? В конце концов, неos объект, который существует вне лямбда и fooобъем?

2 ответа

Решение

Я борюсь с тем, что здесь os не является локальной переменной для foo, он существует вне fooобъем,

Нет, это локальное, оно не существует внеfoo.

Объект, который ссылаетсяos существует вне foo, потому как osэто ссылка. Но здесь это не имеет значения, поскольку мы говорим о переменных, а не об объектах.

Кроме того, почему лямбда не может return os;?

Может, вам просто нужно указать явный тип возвращаемого значения, в противном случае тип возвращаемого значения определяется как std::ostream, т.е. код будет пытаться скопировать поток, и его нельзя копировать.

Но работает следующее:

auto f = [&os]() -> std::ostream& { return os << "Hellow World !" << endl; };

Лямбда сверху компилируется компилятором во что-то похожее на f2 в foo2 (). Таким образом, экземпляр лямбда является локальным внутри foo2, а ссылка (указатель) ostream - это член, изменяемый в локальном экземпляре лямбда.

Таким образом, вы должны убедиться, что лямбда с обернутой ссылкой на ostream не переживает сам ostream (os), чего не происходит в этом случае, потому что экземпляр лямбда живет только в пределах функции -> меньше, чем объем переданного 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;
}
Другие вопросы по тегам