728x90

황기태 저자의 명품 C++ Programming 개정판을 읽고 학습한 내용을 정리한 포스트입니다!

https://search.shopping.naver.com/book/catalog/32436115747

 

C++ Programming : 네이버 도서

네이버 도서 상세정보를 제공합니다.

search.shopping.naver.com

 

auto를 이용한 쉬운 변수 선언

  • auto 키워드는 C++11 표준부터 의미가 수정되어, 변수 선언문으로부터 변수의 타입을 추론하여 결정하도록 지시
  • auto는 복잡한 형식의 변수 선언을 간소하게 해주며, 타입 선언의 오타나 번거로움을 줄이게 해준다
auto pi = 3.14; // 3.14가 실수이므로 pi는 double 타입으로 선언됨
auto n = 3; // 3이 정수이무로 n을 int로 선언
auto *p = &n // 변수 p는 int* 타입으로 선언

int n = 10;
int &ref = n; // ref는 int에 대한 참조 변수로 선언
auto ref2 = ref; // ref2는 int& 타입의 변수로 자동 선언

 

함수의 리턴 타입으로부터 추론하여 변수 타입 선언
int square(int x) { return x*x; }
...
auto ret = square(3); // 변수 ret는 int 타입으로 자동 선언
  • 컴파일러는 square()의 리턴 타입이 int이므로 변수 ret의 타입을 int로 추론한다.
  • square() 함수가 double을 리턴하는 함수로 수정되면 변수 ret의 타입도 double 타입으로 자동 결정
  • auto는 코드의 수정에 따른 오류 가능성을 낮추는 효과가 있다.

 

아래 코드는auto를 사용하여 변수의 타입을 선언하는 다양한 예시이다.

#include <iostream>
#include <vector>
using namespace std;

int square(int x) { return x*x; }

int main() {
	// 기본 타입 선언에 auto 활용
	auto c = 'a'; // c는 char 타입으로 결정
	auto pi = 3.14; // pi은 double 타입으로 결정
	auto ten = 10; // ten은 int 타입으로 결정
	auto *p = &ten; // 변수 p는 int* 타입으로 결정
	cout << c << " " << pi << " " << ten << " " << *p << endl;

	// 함수의 리턴 타입으로 추론
	auto ret = square(3); // square() 함수의 리턴 타입이 int 이므로 ret는 int로 결정
	cout << *p << " " << ret << endl;

	vector<int> v = { 1,2,3,4,5 }; //벡터 v에 5개의 원소, 1,2,3,4,5 삽입
	vector<int>::iterator it;
	for (it = v.begin(); it != v.end(); it++)
		cout << *it << " "; // 1 2 3 4 5 출력
	cout << endl;

	// 템플릿에 auto를 사용하여 복잡한 선언의 간소화
	for (auto it = v.begin(); it != v.end(); it++)
		cout << *it << " "; // 1 2 3 4 5 출력
}

/*
a 3.14 10 10
10 9
1 2 3 4 5
1 2 3 4 5
*/

 


람다 대수와 람다식

  • 람다 대수에서 람다식(lambda expression)은 수학의 함수를 단순하게 표현하는 방법
f(x, y) = x + y

// 람다식
(x, y)-> x + y
  • 수학에서 이름 없는 함수를 람다식이라고 한다. 괄호와 함께 x, y에 대입될 값을 지정하면 람다식의 계산이 이루어진다.

C++에서 람다식 선언

  • 프로그래밍 세계에서 람다는 이름 없는 익명 함수(anonymous function)로, 람다식(lambda expression) 혹은 람다 함수로 불린다.
  • 캡쳐 리스트, 매개 변수 리스트, 리턴 타입, 함수 바디의 4부분으로 구성된다.
                       /* 생략 가능 */
[      ]   (      )   ->   리턴타입   { /* 함수 코드 작성 */ }
[](int x, int y) { cout << x + y; }; // 매개 변수 x, y의 합을 출력하는 람다 식
[](int x, int y) -> int { return x + y; }; // 매개 변수 x, y의 합을 리턴하는 람다 식
[](int x, int y) { cout << x+y; } (2, 3); // x에 2, y에 3을 대입하여 코드 실행

 

캡쳐 리스트
  • 람다식의 외부에 선언된 변수(지역변수, 전역변수) 목록
표현 의미
[x] 변수 x의 값 활용
[&x] 참조 변수 x 활용
[=] 모든 변수의 값 활용
[&] 모든 참조 변수 활용

 


간단한 람다식 만들기

  • 매개 변수 x, y의 합을 출력하는 람다식을 작성해보자.
#include <iostream>  
using namespace std;

int main() {
	// 람다 함수 선언과 동시에 호출(x=2, y=3 전달)
	[](int x, int y) { cout << "합은 " << x + y; } (2, 3); // 5 출력
}

auto로 람다식 저장 및 호출

  • 람다식의 형식은 컴파일러에만 알려져 있기에, 개발자가 람다식을 저장하는 변수를 직접 선언할 수 있다.
  • auto를 이용하여 변수 love에 람다식을 저장하고, love()의 모양으로 람다식을 호출해보자.
#include <iostream>  
#include <string>  
using namespace std;

int main() {
	auto love = [](string a, string b) { 
		cout << a << "보다 " <<  b << "가 좋아" << endl;
	};  

	love("돈", "너"); // 람다식 호출
	love("냉면", "만두"); // 람다식 호출
}

캡쳐 리스트와 리턴 타입을 가지는 람다식 만들기

  • 람다식은 캡쳐 리스트를 이용하여 주변의 non-static 변수들(지역 변수나 멤버 변수)에 대해 값을 복사하여 받거나 참조를 활용할 수 잇다.
  • 아래는 반지름이 r인 원의 면적을 리턴하는 람다식이다.
#include <iostream>  
using namespace std;

int main() {
	double pi = 3.14; // 지역 변수

	auto calc = [pi](int r) -> double { return pi*r*r; }; // 반지름이 r인 원 면적을 리턴하는 람다 함수 작성

	cout << "면적은 " << calc(3); // 람다식 호출. 28.26출력
}

 

  • 아래는 캡쳐 리스트에 참조 활용하여 합을 외부에 저장하는 람다식이다.
#include <iostream>  
using namespace std;

int main() {
	int sum = 0; // 지역 변수

	[&sum](int x, int y) { sum = x + y; } (2, 3); // 합 5를 지역변수 sum에 저장

	cout << "합은 " << sum;
}

STL 템플릿에 람다식 활용

  • STL 함수 for_each()를 이용하여 벡터의 모든 원소를 출력하는 예제이다.
#include <iostream>
#include <vector>
#include <algorithm> // for_each() 알고리즘 함수를 사용하기 위함
using namespace std;

void print(int n) {
	cout << n << " ";
}

int main() {
	vector<int> v = { 1, 2, 3, 4, 5 };

	// for_each()는 벡터 v의 첫번째 원소부터 끝까지 검색하면서,
	// 각 원소에 대해 print(int n) 호출. 매개 변수 n에 각 원소 값 전달
	for_each(v.begin(), v.end(), print);
}
  • 아래는 STL 함수 for_each()와 람다식을 이용하여 벡터의 모든 원소 출력
#include <iostream>
#include <vector>
#include <algorithm> // for_each() 알고리즘 함수를 사용하기 위함
using namespace std;

int main() {
	vector<int> v = { 1, 2, 3, 4, 5 };

	// for_each()는 벡터 v의 첫번째 원소부터 끝까지 검색하면서,
	// 각 원소에 대해 3번째 매개변수인 람다식 호출. 매개변수 n에 각 원소 값 전달
	for_each(v.begin(), v.end(), [](int n) { cout << n << " "; });
}

 

C++에서 람다식의 의미

 

C++ 프로그램 작성 시람다가 꼭 필요한 기능은 아니다. 다만 간단하고 짧게 최적화된 코드를 작성하는데 도움이 되며, 특별히 람다가 유용한 경우는 아래와 같다.

  • 한 번만 호출하고 재사용하지 않기 때문에 함수에 이름을 붙일 필요가 없는 경우
  • STL 알고리즘 함수의 매개 변수에 연산 코드를 넘기는 경우, 연산 코드를 익명의 람다식으로 작성

 

728x90

'Programming Language > C++' 카테고리의 다른 글

[C++] Vector with Cpp  (1) 2023.12.20
[C++] Array with Cpp  (1) 2023.12.20
[C++] 표준 템플릿 라이브러리(STL)  (0) 2023.12.20
[C++] 제네릭 클래스 만들기  (1) 2023.12.19
[C++] 다양한 제네릭 함수 만들기  (0) 2023.12.19