c++ cheatsheet
## C++ Coding Cheat Sheet
### 1. **기본 문법**
#### 변수 선언과 초기화
```cpp
int a = 10;
double b = 3.14;
char c = 'A';
std::string str = "Hello, World!";
```
#### 입출력
```cpp
#include <iostream>
int main() {
int num;
std::cin >> num; // 입력
std::cout << "Number: " << num << std::endl; // 출력
return 0;
}
```
### 2. **제어 구조**
#### 조건문
```cpp
if (condition) {
// 조건이 참일 때
} else if (anotherCondition) {
// 또 다른 조건이 참일 때
} else {
// 모든 조건이 거짓일 때
}
// 삼항 연산자
int result = (a > b) ? a : b;
```
#### 반복문
```cpp
// for 반복문
for (int i = 0; i < 10; i++) {
std::cout << i << std::endl;
}
// while 반복문
int i = 0;
while (i < 10) {
std::cout << i << std::endl;
i++;
}
// do...while 반복문
int j = 0;
do {
std::cout << j << std::endl;
j++;
} while (j < 10);
```
### 3. **기본 데이터 구조**
#### 배열
```cpp
int arr[5] = {1, 2, 3, 4, 5};
std::cout << arr[0] << std::endl; // 배열 요소 접근
```
#### 벡터 (Vector)
```cpp
#include <vector>
std::vector<int> vec = {1, 2, 3, 4, 5};
vec.push_back(6); // 요소 추가
vec.pop_back(); // 마지막 요소 제거
// 요소 접근
for (int i = 0; i < vec.size(); i++) {
std::cout << vec[i] << std::endl;
}
// Range-based for loop
for (int x : vec) {
std::cout << x << std::endl;
}
```
#### 문자열 (String)
```cpp
#include <string>
std::string s = "Hello";
s += " World"; // 문자열 추가
std::cout << s << std::endl; // "Hello World"
// 문자열 길이
std::cout << s.length() << std::endl;
// 부분 문자열
std::cout << s.substr(0, 5) << std::endl; // "Hello"
// 문자열 비교
if (s == "Hello World") {
std::cout << "Equal" << std::endl;
}
```
### 4. **함수**
#### 함수 정의
```cpp
int add(int a, int b) {
return a + b;
}
int main() {
int result = add(3, 4);
std::cout << result << std::endl; // 7
return 0;
}
```
#### 함수 오버로딩
```cpp
int add(int a, int b) {
return a + b;
}
double add(double a, double b) {
return a + b;
}
int main() {
std::cout << add(1, 2) << std::endl; // 3
std::cout << add(1.5, 2.5) << std::endl; // 4.0
return 0;
}
```
#### 재귀 함수
```cpp
int factorial(int n) {
if (n <= 1) return 1;
else return n * factorial(n - 1);
}
int main() {
std::cout << factorial(5) << std::endl; // 120
return 0;
}
```
### 5. **클래스와 객체지향 프로그래밍**
#### 클래스 정의
```cpp
class Person {
public:
std::string name;
int age;
Person(std::string n, int a) : name(n), age(a) {}
void display() {
std::cout << "Name: " << name << ", Age: " << age << std::endl;
}
};
int main() {
Person p("Alice", 30);
p.display(); // Name: Alice, Age: 30
return 0;
}
```
#### 상속
```cpp
class Animal {
public:
void speak() {
std::cout << "Animal speaks" << std::endl;
}
};
class Dog : public Animal {
public:
void speak() {
std::cout << "Dog barks" << std::endl;
}
};
int main() {
Dog d;
d.speak(); // Dog barks
return 0;
}
```
#### 다형성
```cpp
class Animal {
public:
virtual void speak() {
std::cout << "Animal speaks" << std::endl;
}
};
class Dog : public Animal {
public:
void speak() override {
std::cout << "Dog barks" << std::endl;
}
};
int main() {
Animal* a = new Dog();
a->speak(); // Dog barks
delete a;
return 0;
}
```
### 6. **표준 템플릿 라이브러리 (STL)**
#### 맵 (Map)
```cpp
#include <map>
std::map<std::string, int> ages;
ages["Alice"] = 30;
ages["Bob"] = 25;
// 요소 접근
std::cout << "Alice's age: " << ages["Alice"] << std::endl;
// 요소 순회
for (const auto& pair : ages) {
std::cout << pair.first << ": " << pair.second << std::endl;
}
```
#### 셋 (Set)
```cpp
#include <set>
std::set<int> uniqueNumbers = {1, 2, 3, 3, 4};
uniqueNumbers.insert(5);
// 요소 접근
for (int num : uniqueNumbers) {
std::cout << num << std::endl;
}
// 요소 존재 여부 확인
if (uniqueNumbers.count(3)) {
std::cout << "3 is in the set" << std::endl;
}
```
#### 스택 (Stack)과 큐 (Queue)
```cpp
#include <stack>
#include <queue>
// 스택
std::stack<int> stack;
stack.push(1);
stack.push(2);
std::cout << stack.top() << std::endl; // 2
stack.pop();
// 큐
std::queue<int> queue;
queue.push(1);
queue.push(2);
std::cout << queue.front() << std::endl; // 1
queue.pop();
```
### 7. **파일 입출력**
```cpp
#include <fstream>
int main() {
// 파일 쓰기
std::ofstream outFile("output.txt");
outFile << "Hello, World!" << std::endl;
outFile.close();
// 파일 읽기
std::ifstream inFile("output.txt");
std::string content;
while (getline(inFile, content)) {
std::cout << content << std::endl;
}
inFile.close();
return 0;
}
```
### 8. **예외 처리**
```cpp
#include <iostream>
#include <stdexcept>
int divide(int a, int b) {
if (b == 0) throw std::invalid_argument("Division by zero");
return a / b;
}
int main() {
try {
int result = divide(10, 0);
std::cout << result << std::endl;
} catch (const std::exception& e) {
std::cerr << "Error: " << e.what() << std::endl;
}
return 0;
}
```
### 9. **C++11 및 그 이후 기능**
#### 자동 타입 추론 (auto)
```cpp
auto x = 10; // x는 int로 추론됨
auto y = 3.14; // y는 double로 추론됨
```
#### 범위 기반 for 루프
```cpp
std::vector<int> vec = {1, 2, 3, 4, 5};
for (int x : vec) {
std::cout << x << std::endl;
}
```
#### 람다 표현식
```cpp
auto add = [](int a, int b) -> int {
return a + b;
};
std::cout << add(3, 4) << std::endl; // 7
```
#### 스마트 포인터
```cpp
#include <memory>
std::shared_ptr<int> p1 = std::make_shared<int>(10);
std::unique_ptr<int> p2 = std::make_unique<int>(20);
```
### 10. **타입 변환**
#### 명시적 타입 변환
```cpp
double d = 3.14;
int i = static_cast<int>(d); // 3
```
#### 암시적 타입 변환
```cpp
int a = 5;
double b = a;
// 5.0
```
### 11. **고급 데이터 구조**
#### 덱 (Deque)
- 덱은 양쪽 끝에서 요소의 추가와 제거가 가능한 자료구조입니다.
```cpp
#include <deque>
std::deque<int> dq;
dq.push_back(1); // 뒤에 추가
dq.push_front(2); // 앞에 추가
std::cout << dq.front() << std::endl; // 2
dq.pop_front(); // 앞에서 제거
```
#### 우선순위 큐 (Priority Queue)
- 우선순위 큐는 가장 높은 우선순위를 가진 요소가 가장 먼저 제거되는 자료구조입니다.
```cpp
#include <queue>
std::priority_queue<int> pq;
pq.push(5);
pq.push(2);
pq.push(8);
std::cout << pq.top() << std::endl; // 8
pq.pop();
```
### 12. **알고리즘과 유틸리티**
#### 정렬
```cpp
#include <algorithm>
#include <vector>
std::vector<int> vec = {5, 3, 8, 1, 2};
std::sort(vec.begin(), vec.end()); // 오름차순 정렬
std::sort(vec.rbegin(), vec.rend()); // 내림차순 정렬
```
#### 이진 검색
```cpp
#include <algorithm>
#include <vector>
std::vector<int> vec = {1, 2, 3, 4, 5};
bool found = std::binary_search(vec.begin(), vec.end(), 3); // true
```
#### 배열 합계와 최대값
```cpp
#include <numeric>
#include <vector>
std::vector<int> vec = {1, 2, 3, 4, 5};
int sum = std::accumulate(vec.begin(), vec.end(), 0); // 15
int max_element = *std::max_element(vec.begin(), vec.end()); // 5
```
### 13. **메모리 관리**
#### 동적 메모리 할당과 해제
```cpp
int* ptr = new int(5); // 동적 메모리 할당
std::cout << *ptr << std::endl; // 5
delete ptr; // 메모리 해제
int* arr = new int[5];
delete[] arr; // 배열 메모리 해제
```
#### 스마트 포인터 (Smart Pointers)
- C++11부터 제공되는 스마트 포인터는 메모리 관리 문제를 방지하기 위해 자동으로 메모리를 관리합니다.
```cpp
#include <memory>
std::shared_ptr<int> sp = std::make_shared<int>(10);
std::unique_ptr<int> up = std::make_unique<int>(20);
// std::weak_ptr는 std::shared_ptr와 결합해 순환 참조를 방지합니다.
std::weak_ptr<int> wp = sp;
```
### 14. **전처리기와 매크로**
#### 매크로 정의와 사용
```cpp
#define PI 3.14159
#define SQUARE(x) ((x) * (x))
std::cout << "Value of PI: " << PI << std::endl;
std::cout << "Square of 5: " << SQUARE(5) << std::endl;
```
#### 조건부 컴파일
```cpp
#ifdef DEBUG
std::cout << "Debug mode" << std::endl;
#else
std::cout << "Release mode" << std::endl;
#endif
```
### 15. **템플릿**
#### 함수 템플릿
```cpp
template <typename T>
T add(T a, T b) {
return a + b;
}
std::cout << add<int>(3, 4) << std::endl; // 7
std::cout << add<double>(2.5, 3.5) << std::endl; // 6.0
```
#### 클래스 템플릿
```cpp
template <typename T>
class Box {
private:
T value;
public:
Box(T v) : value(v) {}
T getValue() { return value; }
};
Box<int> intBox(123);
Box<double> doubleBox(45.67);
std::cout << intBox.getValue() << std::endl; // 123
std::cout << doubleBox.getValue() << std::endl; // 45.67
```
### 16. **STL 알고리즘**
#### STL의 유용한 알고리즘 함수
```cpp
#include <algorithm>
#include <vector>
#include <iostream>
std::vector<int> vec = {3, 1, 4, 1, 5, 9};
// 최대값과 최소값
int max_val = *std::max_element(vec.begin(), vec.end()); // 9
int min_val = *std::min_element(vec.begin(), vec.end()); // 1
// 특정 값 찾기
auto it = std::find(vec.begin(), vec.end(), 4);
if (it != vec.end()) {
std::cout << "Found: " << *it << std::endl; // 4
}
// 특정 조건에 맞는 첫 번째 요소 찾기
auto isOdd = [](int i){ return i % 2 != 0; };
auto odd_it = std::find_if(vec.begin(), vec.end(), isOdd);
if (odd_it != vec.end()) {
std::cout << "First odd number: " << *odd_it << std::endl; // 3
}
// 모든 요소가 조건을 만족하는지 확인
bool all_positive = std::all_of(vec.begin(), vec.end(), [](int i){ return i > 0; }); // true
// 특정 조건을 만족하는 요소의 개수 세기
int odd_count = std::count_if(vec.begin(), vec.end(), isOdd); // 3
```
### 17. **다중 스레딩과 동기화**
#### 스레드
```cpp
#include <thread>
#include <iostream>
void printHello() {
std::cout << "Hello from thread!" << std::endl;
}
int main() {
std::thread t(printHello);
t.join(); // 스레드가 종료될 때까지 대기
return 0;
}
```
#### 뮤텍스
```cpp
#include <mutex>
#include <thread>
#include <iostream>
std::mutex mtx;
void printHello() {
std::lock_guard<std::mutex> lock(mtx);
std::cout << "Hello from thread!" << std::endl;
}
int main() {
std::thread t1(printHello);
std::thread t2(printHello);
t1.join();
t2.join();
return 0;
}
```
### 18. **문자열과 문자열 스트림**
#### 문자열 스트림
```cpp
#include <sstream>
#include <string>
#include <iostream>
std::string str = "123 456";
std::istringstream iss(str);
int a, b;
iss >> a >> b;
std::cout << "a: " << a << ", b: " << b << std::endl; // a: 123, b: 456
std::ostringstream oss;
oss << a << " + " << b << " = " << (a + b);
std::cout << oss.str() << std::endl; // "123 + 456 = 579"
```
### 19. **공간과 시간 복잡도 분석**
- **공간 복잡도**: 알고리즘이 사용하는 메모리 공간의 양을 측정합니다.
- **시간 복잡도**: 알고리즘이 완료되는 데 걸리는 시간을 측정합니다.
- C++에서는 이를 고려하여 효율적인 알고리즘과 데이터 구조를 설계해야 합니다.
### 20. **표준 라이브러리와 유틸리티**
- **cmath**: 수학 함수
- **cstdlib**: 일반적인 유틸리티 함수
- **ctime**: 시간 관련 함수
- **cassert**: 디버깅을 위한 assert 매크로
- **algorithm**: 다양한 알고리즘 함수
- **numeric**: 수치적 계산을 위한 함수
### 21. **이동 시멘틱스 (Move Semantics)**
#### 이동 생성자와 이동 할당 연산자
- 이동 시멘틱스는 객체의 소유권을 이전할 때 불필요한 복사를 피하기 위해 도입된 개념입니다. 이는 특히 리소스가 많은 객체를 다룰 때 성능을 크게 향상시킬 수 있습니다.
```cpp
#include <iostream>
#include <vector>
class Resource {
public:
int* data;
size_t size;
// 기본 생성자
Resource(size_t size) : size(size), data(new int[size]) {
std::cout << "Resource acquired!" << std::endl;
}
// 소멸자
~Resource() {
delete[] data;
std::cout << "Resource destroyed!" << std::endl;
}
// 이동 생성자
Resource(Resource&& other) noexcept : data(nullptr), size(0) {
*this = std::move(other);
}
// 이동 할당 연산자
Resource& operator=(Resource&& other) noexcept {
if (this != &other) {
delete[] data;
data = other.data;
size = other.size;
other.data = nullptr;
other.size = 0;
}
return *this;
}
};
int main() {
Resource res1(10);
Resource res2 = std::move(res1); // 이동 생성자 호출
return 0;
}
```
### 22. **컨테이너 어댑터 (Container Adapters)**
#### 스택 (Stack)
- LIFO(Last In, First Out) 자료구조로, 가장 최근에 삽입된 요소가 가장 먼저 제거됩니다.
```cpp
#include <stack>
std::stack<int> stack;
stack.push(1);
stack.push(2);
stack.push(3);
std::cout << stack.top() << std::endl; // 3
stack.pop(); // 3 제거
std::cout << stack.top() << std::endl; // 2
```
#### 큐 (Queue)
- FIFO(First In, First Out) 자료구조로, 가장 먼저 삽입된 요소가 가장 먼저 제거됩니다.
```cpp
#include <queue>
std::queue<int> queue;
queue.push(1);
queue.push(2);
queue.push(3);
std::cout << queue.front() << std::endl; // 1
queue.pop(); // 1 제거
std::cout << queue.front() << std::endl; // 2
```
#### 우선순위 큐 (Priority Queue)
- 요소가 우선순위에 따라 정렬되고, 가장 높은 우선순위를 가진 요소가 먼저 제거됩니다.
```cpp
#include <queue>
std::priority_queue<int> pq;
pq.push(10);
pq.push(20);
pq.push(15);
std::cout << pq.top() << std::endl; // 20 (최대값)
pq.pop(); // 20 제거
std::cout << pq.top() << std::endl; // 15
```
### 23. **정규 표현식 (Regular Expressions)**
- C++11부터 정규 표현식 라이브러리가 도입되어 문자열 검색 및 매칭을 쉽게 수행할 수 있습니다.
```cpp
#include <iostream>
#include <regex>
int main() {
std::string target = "The quick brown fox";
std::regex re("(\\w+) (\\w+) (\\w+)");
std::smatch match;
if (std::regex_search(target, match, re) && match.size() > 1) {
std::cout << "Found: " << match.str(0) << std::endl; // 전체 매칭
std::cout << "First word: " << match.str(1) << std::endl; // 첫 번째 그룹
}
return 0;
}
```
### 24. **기타 STL 구성 요소**
#### 리스트 (List)
- 리스트는 이중 연결 리스트로, 요소의 삽입과 삭제가 용이합니다.
```cpp
#include <list>
std::list<int> lst = {1, 2, 3};
lst.push_back(4); // 끝에 추가
lst.push_front(0); // 앞에 추가
lst.pop_back(); // 끝에서 제거
lst.pop_front(); // 앞에서 제거
for (int x : lst) {
std::cout << x << std::endl;
}
```
#### 비트셋 (Bitset)
- 비트셋은 고정된 크기의 비트를 저장하는 컨테이너로, 비트 조작에 유용합니다.
```cpp
#include <bitset>
#include <iostream>
std::bitset<8> bits(std::string("0101"));
std::cout << bits << std::endl; // 00000101
bits.set(1); // 2번째 비트를 1로 설정
std::cout << bits << std::endl; // 00000111
```
### 25. **시간과 날짜**
- C++11부터 시간과 날짜를 다루기 위한 표준 라이브러리 `<chrono>`가 도입되었습니다.
```cpp
#include <iostream>
#include <chrono>
#include <thread>
int main() {
// 현재 시간
auto start = std::chrono::high_resolution_clock::now();
// 1초 대기
std::this_thread::sleep_for(std::chrono::seconds(1));
// 경과 시간 측정
auto end = std::chrono::high_resolution_clock::now();
std::chrono::duration<double> elapsed = end - start;
std::cout << "Elapsed time: " << elapsed.count() << " seconds" << std::endl;
return 0;
}
```
### 26. **유니온 (Union)와 열거형 (Enum)**
#### 유니온 (Union)
- 유니온은 여러 데이터 타입을 하나의 메모리 공간에 저장할 수 있습니다. 유니온의 모든 멤버는 동일한 메모리 공간을 공유합니다.
```cpp
#include <iostream>
union Data {
int intVal;
float floatVal;
char charVal;
};
int main() {
Data data;
data.intVal = 10;
std::cout << "Int: " << data.intVal << std::endl;
data.floatVal = 3.14f;
std::cout << "Float: " << data.floatVal << std::endl;
data.charVal = 'A';
std::cout << "Char: " << data.charVal << std::endl;
return 0;
}
```
#### 열거형 (Enum)
- 열거형은 관련된 상수들을 그룹화하여 코드의 가독성을 높이고 관리하기 쉽게 만듭니다.
```cpp
#include <iostream>
enum Color { RED, GREEN, BLUE };
int main() {
Color color = RED;
if (color == RED) {
std::cout << "Color is RED" << std::endl;
}
// C++11 이후에는 열거형 클래스(enum class)도 사용 가능
enum class TrafficLight { RED, GREEN, YELLOW };
TrafficLight light = TrafficLight::GREEN;
if (light == TrafficLight::GREEN) {
std::cout << "Light is GREEN" << std::endl;
}
return 0;
}
```
### 27. **조건부 연산자와 비트 연산자**
#### 조건부 연산자 (삼항 연산자)
- 조건부 연산자는 간단한 조건문을 대체할 수 있는 표현식입니다.
```cpp
int a = 5, b = 10;
int max = (a > b) ? a : b;
std::cout << "Max: " << max << std::endl; // Max: 10
```
#### 비트 연산자
- C++에서는 비트 연산자를 사용해 비트 단위로 데이터를 조작할 수 있습니다.
```cpp
int a = 5; // 0101
int b = 3; // 0011
std::cout << (a & b) << std::endl; // 1 (AND)
std::cout << (a | b) << std::endl; // 7 (OR)
std::cout << (a ^ b) << std::endl; // 6 (XOR)
std::cout << (~a) << std::endl; // -6 (NOT)
std::cout << (a << 1) << std::endl; // 10 (Left shift)
std::cout << (a >> 1) << std::endl; // 2 (Right shift)
```
### 28. **네임스페이스 (Namespace)**
- 네임스페이스는 이름 충돌을 방지하기 위해 사용됩니다.
```cpp
#include <iostream>
namespace first {
void func() {
std::cout << "Inside first namespace" << std::endl;
}
}
namespace second {
void func() {
std::cout << "Inside second namespace" << std::endl;
}
}
int main() {
first::func();
second::func();
// using을 통해 네임스페이스를 생략할 수 있음
using namespace first;
func(); // Inside first namespace
return 0;
}
```
### 29. **연산자 오버로딩**
연산자 오버로딩은 클래스에 대해 기존 연산자를 사용자 정의 방식으로 동작하게 할 수 있는 기능입니다. 이를 통해 객체 간의 연산을 자연스럽게 표현할 수 있습니다.
#### 기본 연산자 오버로딩
```cpp
#include <iostream>
class Complex {
public:
double real, imag;
Complex(double r = 0.0, double i = 0.0) : real(r), imag(i) {}
// 덧셈 연산자 오버로딩
Complex operator + (const Complex& other) {
return Complex(real + other.real, imag + other.imag);
}
// 출력 스트림 연산자 오버로딩
friend std::ostream& operator << (std::ostream& out, const Complex& c) {
out << c.real << " + " << c.imag << "i";
return out;
}
};
int main() {
Complex c1(3.0, 2.0), c2(1.0, 7.0);
Complex c3 = c1 + c2; // Complex 객체 덧셈
std::cout << c3 << std::endl; // 4 + 9i
return 0;
}
```
### 30. **템플릿 특수화**
템플릿 특수화는 일반 템플릿에서 다루기 힘든 특정 타입에 대해 별도의 처리를 정의하는 기능입니다.
#### 기본 템플릿과 특수화 템플릿
```cpp
#include <iostream>
template <typename T>
class Storage {
public:
T value;
Storage(T v) : value(v) {}
void print() { std::cout << value << std::endl; }
};
// 특수화 템플릿 (char* 타입에 대한 특수화)
template <>
class Storage<char*> {
public:
char* value;
Storage(char* v) : value(v) {}
void print() { std::cout << "Specialized for char*: " << value << std::endl; }
};
int main() {
Storage<int> intStorage(42);
intStorage.print(); // 42
Storage<char*> charStorage("Hello");
charStorage.print(); // Specialized for char*: Hello
return 0;
}
```
### 31. **가상 함수와 순수 가상 함수**
가상 함수는 다형성을 제공하는 핵심 요소입니다. 순수 가상 함수는 파생 클래스가 반드시 구현해야 하는 메서드입니다.
#### 가상 함수
```cpp
#include <iostream>
class Base {
public:
virtual void show() { std::cout << "Base class" << std::endl; }
};
class Derived : public Base {
public:
void show() override { std::cout << "Derived class" << std::endl; }
};
int main() {
Base* b = new Derived();
b->show(); // Derived class
delete b;
return 0;
}
```
#### 순수 가상 함수와 추상 클래스
```cpp
#include <iostream>
class AbstractBase {
public:
virtual void show() = 0; // 순수 가상 함수
};
class ConcreteDerived : public AbstractBase {
public:
void show() override { std::cout << "ConcreteDerived class" << std::endl; }
};
int main() {
ConcreteDerived obj;
obj.show(); // ConcreteDerived class
return 0;
}
```
### 32. **다중 상속과 가상 상속**
C++은 다중 상속을 지원합니다. 가상 상속은 다이아몬드 문제를 해결하는 방법 중 하나입니다.
#### 다중 상속
```cpp
#include <iostream>
class A {
public:
void display() { std::cout << "Class A" << std::endl; }
};
class B {
public:
void display() { std::cout << "Class B" << std::endl; }
};
class C : public A, public B {
public:
void display() {
A::display(); // A의 display 호출
B::display(); // B의 display 호출
}
};
int main() {
C obj;
obj.display(); // Class A Class B
return 0;
}
```
#### 가상 상속
```cpp
#include <iostream>
class A {
public:
void display() { std::cout << "Class A" << std::endl; }
};
class B : virtual public A {};
class C : virtual public A {};
class D : public B, public C {};
int main() {
D obj;
obj.display(); // Class A
return 0;
}
```
### 33. **C++11/14/17/20 표준의 새로운 기능**
C++11부터 최신 C++20까지 다양한 새로운 기능이 추가되었습니다. 몇 가지 유용한 기능을 소개합니다.
#### C++11
- **자동 타입 추론(auto)**: 컴파일러가 변수의 타입을 자동으로 추론합니다.
- **스마트 포인터**: 메모리 관리를 간소화합니다. (std::unique_ptr, std::shared_ptr)
- **람다 표현식**: 익명 함수 객체를 제공합니다.
```cpp
auto lambda = [](int x) { return x + 10; };
std::cout << lambda(5) << std::endl; // 15
```
#### C++14
- **제네릭 람다**: 템플릿 타입 매개변수를 사용할 수 있습니다.
```cpp
auto genericLambda = [](auto x, auto y) { return x + y; };
std::cout << genericLambda(1, 2) << std::endl; // 3
std::cout << genericLambda(1.1, 2.2) << std::endl; // 3.3
```
#### C++17
- **구조화된 바인딩**: 튜플, 구조체 등의 요소를 쉽게 분해할 수 있습니다.
```cpp
#include <tuple>
auto [x, y] = std::make_tuple(1, 2);
std::cout << x << ", " << y << std::endl; // 1, 2
```
- **std::optional**: 값이 없을 수 있는 변수를 안전하게 다룹니다.
```cpp
#include <optional>
std::optional<int> opt = 10;
if (opt) {
std::cout << "Value: " << *opt << std::endl; // Value: 10
}
```
#### C++20
- **코루틴**: 비동기 프로그래밍을 위한 코루틴을 지원합니다.
- **컨셉(Concepts)**: 템플릿의 요구사항을 명시적으로 표현합니다.
### 34. **C++ 예외 안전성**
C++에서 예외 안전성을 보장하는 것은 중요합니다. 예외가 발생했을 때 리소스 누수나 잘못된 상태가 발생하지 않도록 해야 합니다.
```cpp
#include <iostream>
#include <vector>
#include <stdexcept>
class Example {
public:
Example() { std::cout << "Resource acquired!" << std::endl; }
~Example() { std::cout << "Resource released!" << std::endl; }
};
int main() {
try {
Example e;
std::vector<int> v;
v.at(1) = 10; // std::out_of_range 예외 발생
} catch (const std::exception& e) {
std::cerr << "Exception: " << e.what() << std::endl;
}
return 0;
}
```
### 35. **C++의 디버깅과 프로파일링**
- **assert**: 디버그 빌드에서 조건이 거짓일 때 프로그램을 종료합니다.
```cpp
#include <cassert>
int main() {
int x = 5;
assert(x == 5); // 조건이 참이므로 계속 진행
assert(x == 0); // 조건이 거짓이므로 프로그램 종료
return 0;
}
```
- **gdb**: GNU 디버거는 C++ 프로그램의 디버깅을 지원합니다. 브레이크포인트 설정, 단계별 실행, 변수 상태 검사 등이 가능합니다.
### 36. **라이브러리 확장 및 링크**
C++에서는 자체 라이브러리를 만들고 사용하거나, 다른 라이브러리와 연결할 수 있습니다.
#### 정적 라이브러리와 동적 라이브러리
- **정적 라이브러리**: 컴파일 시 프로그램에 포함됩니다.
- **동적 라이브러리**: 런타임에 로드됩니다.
```cpp
// 정적 라이브러리 예: libexample.a
// 컴파일 시: g++ main.cpp -L. -lexample
// 동적 라이브러리 예: libexample.so
// 컴파일 시: g++ main.cpp -L. -lexample
// 실행 시: LD_LIBRARY_PATH=. ./a.out
```
### 37. **C++의 메타프로그래밍**
메타프로그래밍은 프로그램이 컴파일 시점에 코드를 생성하거나 변형하는 기법입니다. C++에서는 주로 템플릿 메타프로그래밍(TMP)을 사용합니다.
#### 템플릿 재귀와 조건부 컴파일
템플릿을 이용한 재귀 호출과 조건부 컴파일을 통해 컴파일 타임에 계산을 수행할 수 있습니다.
```cpp
#include <iostream>
// 팩토리얼 계산을 위한 템플릿 메타프로그래밍
template<int N>
struct Factorial {
static const int value = N * Factorial<N - 1>::value;
};
template<>
struct Factorial<0> {
static const int value = 1;
};
int main() {
std::cout << "Factorial of 5: " << Factorial<5>::value << std::endl; // 120
return 0;
}
```
### 38. **C++의 고급 입출력**
#### 파일 스트림을 이용한 바이너리 파일 입출력
텍스트가 아닌 바이너리 데이터를 파일에 읽고 쓰는 방법입니다.
```cpp
#include <iostream>
#include <fstream>
struct Data {
int a;
double b;
};
int main() {
Data data = {1, 3.14};
// 바이너리 파일 쓰기
std::ofstream outFile("data.bin", std::ios::binary);
outFile.write(reinterpret_cast<char*>(&data), sizeof(Data));
outFile.close();
Data readData;
// 바이너리 파일 읽기
std::ifstream inFile("data.bin", std::ios::binary);
inFile.read(reinterpret_cast<char*>(&readData), sizeof(Data));
inFile.close();
std::cout << "Read data: " << readData.a << ", " << readData.b << std::endl;
return 0;
}
```
#### 스트림 조작자 (Manipulators)
스트림 조작자는 입출력 형식을 변경하는 데 사용됩니다.
```cpp
#include <iostream>
#include <iomanip>
int main() {
double pi = 3.141592653589793;
std::cout << std::fixed << std::setprecision(3) << pi << std::endl; // 3.142
std::cout << std::scientific << std::setprecision(2) << pi << std::endl; // 3.14e+00
std::cout << std::hex << 255 << std::endl; // ff
std::cout << std::dec << 255 << std::endl; // 255
return 0;
}
```
### 39. **다형성와 객체 수명 주기 관리**
#### 가상 소멸자
기본 클래스에서 소멸자가 가상 함수가 아닌 경우, 파생 클래스 객체를 삭제할 때 메모리 누수가 발생할 수 있습니다.
```cpp
#include <iostream>
class Base {
public:
Base() { std::cout << "Base Constructor" << std::endl; }
virtual ~Base() { std::cout << "Base Destructor" << std::endl; }
};
class Derived : public Base {
public:
Derived() { std::cout << "Derived Constructor" << std::endl; }
~Derived() { std::cout << "Derived Destructor" << std::endl; }
};
int main() {
Base* obj = new Derived();
delete obj; // 올바른 소멸자 호출
return 0;
}
```
### 40. **네임스페이스 고급 사용법**
#### 익명 네임스페이스
익명 네임스페이스를 사용하여 특정 파일 내에서만 접근 가능한 이름을 정의할 수 있습니다. 이는 전역 변수의 가시성을 제한하는 데 유용합니다.
```cpp
#include <iostream>
namespace {
int hiddenValue = 42;
void printHiddenValue() {
std::cout << "Hidden Value: " << hiddenValue << std::endl;
}
}
int main() {
printHiddenValue(); // Hidden Value: 42
return 0;
}
```
### 41. **객체 수명과 소유권**
#### RAII (Resource Acquisition Is Initialization)
C++의 RAII는 리소스 관리 기법으로, 객체의 수명 주기에 따라 리소스를 자동으로 할당하고 해제하는 패턴입니다.
```cpp
#include <iostream>
#include <fstream>
class FileWrapper {
public:
FileWrapper(const std::string& filename) : file(filename) {
if (!file.is_open()) {
throw std::runtime_error("Cannot open file");
}
}
~FileWrapper() {
file.close();
}
void write(const std::string& content) {
file << content << std::endl;
}
private:
std::ofstream file;
};
int main() {
try {
FileWrapper file("example.txt");
file.write("Hello, World!");
} catch (const std::exception& e) {
std::cerr << e.what() << std::endl;
}
return 0;
}
```
### 42. **확장된 유틸리티 기능**
#### std::variant와 std::visit
C++17에서 도입된 `std::variant`는 여러 타입 중 하나를 가질 수 있는 타입 안전 유니언입니다.
```cpp
#include <iostream>
#include <variant>
int main() {
std::variant<int, float, std::string> var;
var = 10;
std::cout << std::get<int>(var) << std::endl;
var = 3.14f;
std::cout << std::get<float>(var) << std::endl;
var = "Hello, Variant!";
std::cout << std::get<std::string>(var) << std::endl;
// std::visit을 이용한 방문자 패턴
std::visit([](auto&& arg) { std::cout << arg << std::endl; }, var);
return 0;
}
```
#### std::any
C++17의 `std::any`는 임의의 타입을 저장할 수 있는 타입 안전 컨테이너입니다.
```cpp
#include <iostream>
#include <any>
int main() {
std::any a = 1;
a = 3.14;
a = std::string("Hello");
try {
std::cout << std::any_cast<std::string>(a) << std::endl;
} catch (const std::bad_any_cast& e) {
std::cerr << "Bad any cast: " << e.what() << std::endl;
}
return 0;
}
```
#### std::filesystem
C++17의 `std::filesystem`은 파일 시스템 작업을 위한 기능을 제공합니다.
```cpp
#include <iostream>
#include <filesystem>
int main() {
std::filesystem::path p = "example.txt";
if (std::filesystem::exists(p)) {
std::cout << "File size: " << std::filesystem::file_size(p) << " bytes" << std::endl;
std::filesystem::rename(p, "new_example.txt");
std::cout << "File renamed" << std::endl;
}
return 0;
}
```
### 43. **고급 템플릿 기능**
#### 부분 특수화 (Partial Specialization)
부분 특수화는 템플릿 매개변수의 일부만 특수화할 수 있습니다.
```cpp
#include <iostream>
template<typename T, typename U>
class Pair {
public:
T first;
U second;
Pair(T f, U s) : first(f), second(s) {}
void print() const {
std::cout << first << ", " << second << std::endl;
}
};
// 부분 특수화: 두 번째 타입이 int인 경우
template<typename T>
class Pair<T, int> {
public:
T first;
int second;
Pair(T f, int s) : first(f), second(s) {}
void print() const {
std::cout << first << ", integer: " << second << std::endl;
}
};
int main() {
Pair<std::string, int> p1("Number", 42);
p1.print(); // Number, integer: 42
Pair<int, double> p2(1, 3.14);
p2.print(); // 1, 3.14
return 0;
}
```
댓글
댓글 쓰기