C ++ Lambdas, Capturing, Smart Ptrs и Stack: почему это работает?

Я экспериментировал с некоторыми новыми функциями в C ++ 11, и я попытался написать следующее программа, ожидая, что она не сработает. К моему большому удивлению, она работает (в GCC 4.6.1 на Linux x86 с флагом 'std = c ++ 0x'):

#include <functional>
#include <iostream>
#include <memory>

std::function<int()> count_up_in_2s(const int from) {
    std::shared_ptr<int> from_ref(new int(from));
    return [from_ref]() { return *from_ref += 2; };
}

int main() {
    auto iter_1 = count_up_in_2s(5);
    auto iter_2 = count_up_in_2s(10);

    for (size_t i = 1; i <= 10; i++)
        std::cout << iter_1() << '\t' << iter_2() << '\n'
        ;
}

Я ожидал, что 'from_ref' будет удален, когда каждое выполнение возвращенной лямбды выполняется. Вот мои рассуждения: после запуска count_up_in_2s из стека выскакивает from_ref, но поскольку возвращенная лямбда не обязательно сразу запускается, поскольку она возвращается, другой ссылки для короткий период до тех пор, пока та же ссылка не будет возвращена при фактическом запуске лямбда-выражения, поэтому не должен ли счетчик ссылок shared_ptr достигнуть нуля, а затем удалить данные?

Если только захват лямбда-выражения C ++ 11 не намного умнее, чем Я отдаю ему должное, и если это так, я буду рад.Если это так, могу ли я предположить, что захват переменных C ++ 11 позволит использовать все хитрости лексической области видимости / закрытия а-ля Lisp, пока / something / заботится о динамически выделяемой памяти? Могу ли я предположить, что все захваченные ссылки останутся в живых до тех пор, пока не будет удалена сама лямбда, что позволит мне использовать smart_ptrs описанным выше способом?

Если это так, как я думаю, не означает ли это, что C ++ 11 позволяет выразительное программирование высшего порядка? Если это так, то я думаю, что комитет C ++ 11 проделал отличную работу =)

8
задан Louis 19 December 2011 в 04:13
поделиться