일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
31 |
- rao
- Dreamhack
- Image Processing
- bloc
- Got
- pytorch
- 파이토치 트랜스포머를 활용한 자연어 처리와 컴퓨터비전 심층학습
- Widget
- Flutter
- system hacking
- llm을 활용 단어장 앱 개발일지
- C++
- ML
- Computer Architecture
- PCA
- ARM
- BAEKJOON
- fastapi를 사용한 파이썬 웹 개발
- BOF
- DART
- Kaggle
- BFS
- study book
- Algorithm
- MDP
- MATLAB
- Stream
- 영상처리
- 백준
- FastAPI
- Today
- Total
Bull
[C++/syntax] Lambda (람다식) 본문
개념
C++에서 람다 식은 익명 함수를 생성하기 위한 간결한 방법을 제공한다.
C++11부터 도입된 람다는 런타임에 정의되며, 주로 알고리즘에서 콜백 함수를 제공하거나,
스코프 내의 변수를 캡처하여 사용하는 용도로 활용한다.
람다 식의 기본 구조
바로 호출하는 경우
[캡처](매개변수 목록) {
// 함수 본문
}(인자들);
초기화하는 경우
변수 = [캡처](매개변수 목록) -> 반환 타입 {
// 함수 본문
// return ~;
}(인자들);
[](){}()로 외우면 편하다.
캡처 목록
람다가 외부 스코프의 변수를 사용할 때, 그 변수들을 어떻게 캡처할 것인지를 정의한다.
값으로 캡처할지([=]), 참조로 캡처할지([&]), 혹은 특정 변수만 선택적으로 캡처할지([x, &y]) 결정할 수 있다.
매개변수 목록
함수와 같이, 람다 식도 매개변수를 가질 수 있다.
매개변수가 필요 없는 경우 이 부분을 비워 둘 수 있습니다.
반환 타입
C++14부터는 반환 타입을 명시적으로 적지 않아도 컴파일러가 반환 타입을 추론할 수 있다.
그러나 복잡한 람다 식에서는 명시적으로 반환 타입을 제공하는 것이 좋다.
인자들
람다 함수에 전달될 인자를 나타낸다.
이 방식은 람다 식이 정의된 직후에 한 번만 실행되어야 할 때 유용하다.
반환 타입을 명시하는 부분은 여전히 람다 식의 시작 부분에서 정의되어야 하며, 람다 식을 호출하는 괄호는 람다 본문 뒤에 위치한다.
예시
캡처X, 반환X
auto printMessage = []() {
std::cout << "Hello, World!" << std::endl;
};
printMessage(); // 출력: Hello, World!
캡처O, 반환X
std::string message = "Hello, C++!";
auto printCustomMessage = [message]() {
std::cout << message << std::endl;
};
printCustomMessage(); // 출력: Hello, C++!
캡처X, 반환O
auto add = [](int x, int y) -> int {
return x + y;
};
std::cout << "The sum is: " << add(5, 3) << std::endl; // 출력: The sum is: 8
캡처O, 반환O
int factor = 2;
auto multiply = [factor](int x) -> int {
return x * factor;
};
std::cout << "The result is: " << multiply(5) << std::endl; // 출력: The result is: 10
바로 호출(인자X)
[]() {
std::cout << "Hello, World!" << std::endl;
}();
바로 호출(인자O)
[](int x, int y) {
std::cout << "Sum: " << x + y << std::endl;
}(10, 5);
응용
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
std::vector<int> v = {1, 2, 3, 4, 5};
int multiplier = 2;
// 모든 요소에 대해 multiplier를 곱하고 결과를 출력
std::for_each(v.begin(), v.end(), [multiplier](int &n) {
n *= multiplier;
std::cout << n << " ";
});
return 0;
}
>>> 2 4 6 8 10
캡처를 사용하는 이유?
같은 블록에 있는 변수인데 왜 캡처에 변수를 따로 넣어주는건지?
캡처에 안넣어도 사용할 수 있다고 생각했는데...
C++의 람다 식 설계와 스코프 관리 규칙에 의하면,
람다 식은 본질적으로 익명의 함수 객체이며, 자신이 정의된 스코프 외부의 변수에 접근할 때 특별한 규칙을 따라야 한다.
(즉, 외부 스코프 변수에 바로 접근이 불가하다는 것. 실제로 캡처에 안넣고 하면 에러난다.)
1. 안전한 접근 보장
외부 스코프의 변수를 람다 내에서 사용할 때, 그 변수가 람다가 실행되는 시점에도 유효한 상태임을 보장하기 위함이다.
값으로 캡처하면 해당 시점의 변수 값을 복사하여 람다 함수 내에서 안전하게 사용할 수 있다.
참조로 캡처하면, 람다 실행 시 변수가 유효한 스코프에 있음을 개발자가 보장해야 한다.
2. 명시성과 의도의 명확화
캡처 목록을 사용함으로써 람다가 어떤 외부 변수에 의존하고 있는지 명확하게 표현된다.
이는 코드의 의도를 명확히 하고, 유지보수성을 향상시키는 데 도움이 된다.
3. 스코프와 생명주기 관리
람다 식이 실행될 때 외부 변수가 더 이상 유효하지 않을 수도 있는 상황(예: 변수의 스코프를 벗어나는 경우)을 관리한다.
변수를 캡처함으로써 람다 식이 해당 변수의 복사본 또는 참조를 안전하게 보관할 수 있게 한다.
4. 유연성 제공
캡처 목록을 통해 개발자는 람다가 접근해야 하는 외부 변수를 유연하게 선택할 수 있다.
모든 외부 변수를 자동으로 캡처하는 것([=] 또는 [&])과 달리, 특정 변수만 선택적으로 캡처할 수도 있다([x, &y]).
이는 불필요한 캡처를 피하고, 메모리 사용과 성능에 영향을 줄 수 있는 요소를 최적화하는 데 도움이 된다.
'Computer Language > C++' 카테고리의 다른 글
[C++] vscode 스니펫 설정 방법 (0) | 2024.03.28 |
---|---|
[C++/lib:algorithm] stable_sort()(안정적으로 정렬) (0) | 2024.03.21 |
[C++/lib:sstream] 문자열 파싱하기 (토큰화) (0) | 2024.03.10 |
[C++/keyword] noexcept (0) | 2023.09.12 |