2013-03-25 2 views
7

다음 내용이 있다고 가정합니다.람다 표현식이`this`를 비열하게 캡처 함

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; }; 
    } 
} 

이제 다음 코드를 작성했습니다. f#f1, f2, f3, f4, f5 어떠한 언급된다

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

. (f5)를 호출 할 때

  1. 반환 (5), 또는
  2. 는 역 참조 nullptr (f1, f2, f3, f4)를 시도 추락 :

    이 기능은 두 가지 중 하나의 동작을 전시하고 있습니다.

일부는 암시 적 또는 명시 적으로 A의 멤버 함수에 "this"을 캡처하기 때문에이 사실을 알고 있습니다.

행동 1 또는 2를 결정하는 공식 규칙은 무엇입니까?

가 나는 this를 캡처 할 생각이 x을 캡처 할 생각을 결코, f1 비슷한에 의해 발생 된 버그를 다루는 동안을 보냈다, 그래서 나는이 문서화하기가 유용하다고 생각.

답변

8

이 동작을 결정하는 공식 규칙은 없습니다. 이 동작은 이므로 정의되지 않음입니다.

람다가 존재하지 않는 개체에 액세스 중입니다. 값을 사용하여 멤버 변수를 직접 캡처 할 수는 없습니다. 당신은 항상 그들을 this에 의해 붙잡는다. 즉, 참조로 캡처하는 것입니다. 개체가 삭제되면 삭제 된 개체에 액세스하려고하면 정의되지 않은 동작이 발생합니다.

예외는 f5이며, 이는 일관된 값을 반환해야합니다. 원본 개체에서 완전히 연결이 끊어졌습니다.

+0

오 - 나는 'f1, f2, f3, f4' 및 f5' 그룹을 거꾸로 분류했습니다! 네, 올바르게 작동하는 것은'f5'이고, 그렇지 않은 것들입니다. 편집 됨. –