2013-03-25 15 views
7

Załóżmy, że mam następujące.Wyraz Lambda podstępnie przechwytujący "ten"

struct A 
{ 
    int x; 
    std::function<int()> f1() { return [=](){ return x; }; } 
    std::function<int()> f2() { return [=](){ return this->x; }; } 
    std::function<int()> f3() { return [this](){ return x; }; } 
    std::function<int()> f4() { return [this](){ return this->x; }; } 
    std::function<int()> f5() 
    { 
     int temp = x; 
     return [=](){ return temp; }; 
    } 
} 

A teraz mam następujący kod.

auto a = std::make_shared<A>(); 
a->x = 5; 
std::function<int()> f = a.f#(); 
a.reset(); 
int x = f(); 

gdzie f# odnosi się do każdego z f1, f2, f3, f4, f5.

Funkcje te wykazujących działanie w jednym z dwóch zestawów:

  1. powrotu 5, gdy jako (f5) lub
  2. awarii próby dereference nullptr (f1, f2, f3, f4).

Rozumiem, że to dlatego, że niektóre z nich są przechwytywanie „this” w funkcji członkowskim A, bezpośrednio lub pośrednio.

Jaka jest formalna reguła określająca zachowanie 1 lub 2?

Spędziłem natomiast do czynienia z błędem, który został spowodowany przez coś podobnego do f1, myśląc, że to uchwycić x i nigdy nie biorąc pod uwagę, że to uchwycić this, więc pomyślałem, że wskazane byłoby, aby to udokumentować.

Odpowiedz

8

Nie istnieje żadna formalna reguła określająca to zachowanie. Ponieważ to zachowanie jest niezdefiniowane.

Twoje lambdy uzyskują dostęp do obiektu, który nie istnieje. Nie można przechwycić zmiennej składowej bezpośrednio według wartości; zawsze przechwytujesz je przez this. Co oznacza, że ​​przechwytujesz je przez odniesienie. Po usunięciu obiektu każda próba uzyskania dostępu do usuniętego obiektu powoduje niezdefiniowane zachowanie.

Wyjątkiem jest f5, który powinien zwracać stałą wartość, gwarantowaną. Jest całkowicie odłączony od obiektu źródłowego.

+0

Oh - Nazwałam grupy 'f1, f2, f3, f4' i' f5' wstecz! Tak, chodzi mi o to, że to "f5" działa poprawnie, a pozostałe nie. Edytowane. –

Powiązane problemy