2016-04-01 12 views
5

Poniższy kod kompiluje, ale daje niezdefiniowane wyjście w VC++ 2015 (wydanie) i błąd runtime z other compilers.Przypisywanie std :: function <int(int)> do std :: function <const int i (const int & x)>

#include <functional> 
#include <iostream> 
int main() 
{ 
    std::function<int(int)> f = [](int x) { return x; }; 
    std::function<const int&(const int& x)> g = f; 
    std::cout << g(42) << std::endl; 
} 

Dlaczego dozwolone jest zadanie g = f;?

+0

kompiluje i wykonuje doskonale z Apple Clang –

+1

Bardzo istotne/możliwe dupe: http://stackoverflow.com/q/32871606/2069064 – Barry

Odpowiedz

5

Rozważmy równoważną kod przepisany uniknąć lambdy lub std::function:

int f(int x) { return x; } 
int const& g(int const& x) { return f(x); } 

to doskonale uformowaną kod, który jednak powraca dangling odniesienie do tymczasowego i tym samym końcu spowodować nieokreśloną zachowanie. Oryginalny kod jest vaid z tego samego powodu: można niejawnie przekonwertować obiekt na odniesienie tego samego typu. W tym przypadku niefortunne.

+0

Dzięki. Twój przykład przynajmniej [generuje ostrzeżenie] (http://codepad.org/o6ejBjn6). Przykład z 'std :: function' nie działa. –

4

Wartość r można powiązać z const&. A const& można przekonwertować na wartość r.

Zbadać to:

int f(int x){return x;} 
int const& g(int const& x){ return f(x); } 

Podobnie wywołanie g jest legalne, nie ma żadnych błędów, ale czytając wynik g(42) jest UB - odniesienie zwisa.

Dobry kompilator zobaczy referencję związaną z tymczasowym zwracaniem i ostrzeganiem.

function po prostu sprawdza, czy typy można konwertować między; nie wykonuje analizy cyklu życia. Być może powinien, ponieważ możemy wykryć ten błąd statycznie.

Powiązane problemy