C ++ 람다 식의 수명은 얼마입니까?
( C ++에서 람다 파생 암시 적 펑터의 수명은 무엇입니까?를 이미 읽었 으며 질문에 대한 답변은 없습니다.)
C ++ 람다 구문은 호출 연산자와 일부 상태를 사용하여 익명 클래스의 인스턴스를 만들기위한 설탕 일 뿐이라는 것을 이해하고 해당 상태의 수명 요구 사항을 이해합니다 (참조로 방송 여부에 따라 결정됨). 람다 자체의 수명? 다음 예에서 std::function
반환 된 인스턴스가 유용할까요?
std::function<int(int)> meta_add(int x) {
auto add = [x](int y) { return x + y; };
return add;
}
그렇다면 어떻게 작동 합니까? 이 나에게 너무 많은 마술처럼. std::function
내가 가지고있는 것에 따라 매우 무거울 수있는 전체 인스턴스 를 복사하는 것만으로 작동하는 것을 상상할 수 있습니다. 과거에는 std::function
기본적으로 함수 포인터를 사용합니다. 빨리. std::function
의 유형 삭제 문제가있는 것 입니다.
수명은 람다를 손으로 굴린 펑터로 교체 한 경우와 정확히 일치합니다.
struct lambda {
lambda(int x) : x(x) { }
int operator ()(int y) { return x + y; }
private:
int x;
};
std::function<int(int)> meta_add(int x) {
lambda add(x);
return add;
}
객체는 meta_add
함수에 로컬로 생성 된 다음 [값을 포함하여 x
]를 반환 값으로 이동 한 다음 로컬 인스턴스가 범위를 벗어나서 삭제됩니다. 그러나 함수에서 반환 된 std::function
객체는이를 보유한 객체가 수행하는 한 유효합니다 . 얼마나 오래 존재하는 호출이 호출되는지.
std::function
람다보다 더 혼란스러워 .
std::function
유형 삭제라는 기술을 사용합니다. 여기에 빠른 비행이 있습니다.
class Base
{
virtual ~Base() {}
virtual int call( float ) =0;
};
template< typename T>
class Eraser : public Base
{
public:
Eraser( T t ) : m_t(t) { }
virtual int call( float f ) override { return m_t(f); }
private:
T m_t;
};
class Erased
{
public:
template<typename T>
Erased( T t ) : m_erased( new Eraser<T>(t) ) { }
int do_call( float f )
{
return m_erased->call( f );
}
private:
Base* m_erased;
};
유형을 지우려는 이유는 무엇입니까? 우리가 원하는 유형이 int (*)(float)
아닙니까?
유형 삭제가 허용하는 것은 Erased
이제와 같이 호출 가능한 모든 값을 수있는 것 int(float)
입니다.
int boring( float f);
short interesting( double d );
struct Powerful
{
int operator() ( float );
};
Erased e_boring( &boring );
Erased e_interesting( &interesting );
Erased e_powerful( Powerful() );
Erased e_useful( []( float f ) { return 42; } );
이 :
[x](int y) { return x + y; };
다음과 동일 : (또는 고려할 수 있음)
struct MyLambda
{
MyLambda(int x): x(x) {}
int operator()(int y) const { return x + y; }
private:
int x;
};
그래서 당신의 개체는 그와 같은 개체를 반환합니다. 잘 정의 된 복사 생성자가 있습니다. 따라서 함수에서 올바르게 복사 할 수 있다는 것이 매우 합리적입니다.
게시 한 코드에서 :
std::function<int(int)> meta_add(int x) {
auto add = [x](int y) { return x + y; };
return add;
}
std::function<int(int)>
함수에 의해 리턴되는 오브젝트가 실제로 로컬 변수에 할당 된 람다 함수 객체의 이동 된 인스턴스를 보유하고있다 add
.
값 또는 참조로 캡처하는 C ++ 11 람다를 정의하면 C ++ 컴파일러는 람다가 호출되거나 변수에 할당 될 때 생성되는 인스턴스 인 고유 함수 형식을 자동으로 생성합니다. 설명을 위해 C ++ 컴파일러는에 의해 정의 된 람다에 대해 다음 클래스 유형을 생성 할 수 있습니다 [x](int y) { return x + y; }
.
class __lambda_373s27a
{
int x;
public:
__lambda_373s27a(int x_)
: x(x_)
{
}
int operator()(int y) const {
return x + y;
}
};
그러면 meta_add
함수는 본질적으로 다음과 같습니다.
std::function<int(int)> meta_add(int x) {
__lambda_373s27a add = __lambda_373s27a(x);
return add;
}
편집 : 그건 그렇고, 당신이 이것을 알고 있는지 확실하지 않지만 이것은 C ++ 11에서 함수 커링 의 예입니다 .
참고 URL : https://stackoverflow.com/questions/7941562/what-is-the-lifetime-of-ac-lambda-expression
'ProgramingTip' 카테고리의 다른 글
scanf ()는 버퍼에 새 줄 문자를 남깁니다. (0) | 2020.11.18 |
---|---|
bash를 호출하고 새 셸 내에서 명령을 실행 한 다음 사용자에게 제어권을 다시 제공하는 방법은 무엇입니까? (0) | 2020.11.18 |
catch를 시도해보십시오. (0) | 2020.11.18 |
grep 명령 결과를 쉘의 일부 변수에 저장하는 방법 (0) | 2020.11.18 |
Angular2의 (keyup) 옵션은 무엇입니까? (0) | 2020.11.18 |