2016-09-01 5 views
3

После изучения лямбда в C++ 11, я написал это и путался с выходом.Смущенный выход лямбда в этом случае

auto f1 = []() { 
    int tmp = 10; 
    int *tmp_p = &tmp; 
    return [tmp_p] (int x) { 
     return *tmp_p + x; 
    }; 
}(); 

auto f2 = []() { 
    int tmp = 10; 
    return [&tmp] (int x) { 
     return tmp + x; 
    }; 
}(); 

cout << f1(5) << endl; 
cout << f1(5) << endl; 

cout << f2(5) << endl; 
cout << f2(5) << endl; 

Выход:

15 
5772973 
2686617 
2686617 

В чем причина этого?

+3

Но они возвращают лямбда с параметрами и выполняются немедленно –

+0

@ AdrianJałoszewski Извините, только что заметили –

ответ

7

Потому что неопределенное поведение.

tmp получает разрушение после присвоения f1, и поэтому tmp_p становится оборванным указателем. Все может произойти, если вы разыщите его, в том числе иногда заданное значение 15, а иногда и не 5772973.

То же самое касается f2, но вместо использования указателя вы используете ссылку, которая ссылается на разрушенный объект, который также является неопределенным поведением.

5

Это то, что мы называем undefined behavior. Почему ваш код вызывает неопределенное поведение?

Первый случай: f1(): Это вызывает его, потому что после вызова эти лямбды значения int tmp и int *tmp_p не на стеке больше (int *tmp_p был скопирован, но int tmp был удален).

Второй корпус: f2(): Доступно значение tmp со ссылкой на внутреннюю лямбду. После завершения создания лямбда его больше не было в стеке, и что-то получило память и записало в нее мусор.

Смежные вопросы