참고 자료: 인프런 <객체지향 개념에 바탕을 둔 Modern C++프로그래밍>
동적 배열을 캡슐화한 순차 컨테이너
#include <iostream>
#include <vector>
#include <algorithm>
#include <random>
int main() {
vector<int> vec {0,1,2,3};
vec.push_back(4); // 끝에 요소 추가
vec.pop_back(); // 끝 요소 삭제
}
vec.size()
<- 원소들 개수
vec.capacity()
<- 추가 공간까지 해서 공간 크기
int intA[3] = {10, 20, 30};
vector<int> vint2(intA, intA + 3);
for(unsigned int i = 0; i < vint2.size(); i++) {
cout << vint2[i] << " "; // 10 20 30
cout << vint2.at(i) << " "; // 위랑 똑같
}
vint2.resize(5); // size: 5, capacity: 6
vint2.shrink_to_fit(); // size: 5, capacity: 6
-> begin(), end() 이런것도 iterator여서 값 아니고 포인터임 주소!!!참조!!!!!
vector<int> vInt(5);
for( vector<int>::iterator it = vInt.begin(); it != vInt.end(); ++it) {
*it = 20;// 원소의 값을 지정함
cout << *it << " "; // 20
}
cout << endl;
// C++11 ~
for(int &v: vInt) {
v = 20;
cout << v << " ";
}
//const_iterator도 있음 그냥 상수
vector<int> vInt3{1,2,3,4,5}; // list 초기화
random_device rd;
shuffle(vInt3.begin(), vInt3.end(), default_random_engine(rd()));
for(const int& v: vInt3) {
cout << v << " ";
}
cout << endl;
sort(vInt3.begin(), vInt3.end());
for(const int& v: vInt3) {
cout << v << " ";
}
inline int max(const int i, const int j) {
return (i > j) ? i : j;
}
cout << max(10, 20) << endl; // 20
max 함수 주소 호출이 아니라, 코드가 저 자리에 들어가서 실행되는 구조~
#define unsafeABS(i) ( (i) >= 0 ? (i) : (-i) ) // 매크로
inline int safeABS(int i) { return i >= 0 ? i : -i; } // 인라인
매크로랑 인라인의 동작 구조를 비교해보자
// inline vs 매크로:
// 1. inline
int x = -10;
cout << safeABS(x++) << endl; // 10
// 2. macro
int y = -10;
cout << unsafeABS(y++) << endl; // 9
똑같은 코드의 절댓값 구하는 매크로, 인라인 함수의 반환값이 각각 10, 9로 다르다.
왜냐면 매크로는 컴파일 전에 전처리기에서 처리된다. y++ 값이 들어가서, 10이 아니라 9가 반환된다.
int incrementCount() {
**static** int counter = 0;
counter++;
return counter;
}
int sumUpTo(const int upTo) {
int sum = 0;
for(int i=1; i<= upTo; i++) {
sum += i;
}
return sum;
}
위 함수에서 counter는 static, sum은 그냥 내부 지역변수로 선언해줬따.
while(true) {
int number;
cin >> number;
if(number <= 0) {
break;
}
const int counter = incrementCount();
cout << "counter: " << counter << endl;
const int sum = sumUpTo(number);
cout << "sum of 1 to " << number << ": " << sum << endl;
}
돌려보면, 저 지역변수는 계속 초기화되지만, static으로 선언한 카운트는 값이 유지된다.
enum Grade {
FRESH = 1,
SOPHOMORE,
JUNIOR,
SENIOR
};
string getGradeLabel_1(const Grade grade) { // 방법1. 낮은 성능 유발
const string gradeLabels[] = { "Fresh", "Sophomore", "Junior", "Senior" };
return gradeLabels[grade-1];
} // string을 반환할 때 복사한 값을 반환하는거다
// 참조를 반환
string& getGradeLabel_2(const Grade grade) { // 방법2. 안전하지 않음
string gradeLabels[] = { "Fresh", "Sophomore", "Junior", "Senior" }; // 지역변수
return gradeLabels[grade-1];
}// -> 지역변수의 참조를 반환하는건 안전하지 않아. 없어진 메모리를 참조할 수 있어서.
string& getGradeLabel_3(const Grade grade) { // 방법3. 가장 바람직
static string gradeLabels[] = { "Fresh", "Sophomore", "Junior", "Senior" };
return gradeLabels[grade-1];
} // static으로 선언한 지역변수는 메모리에서 안없어지니까 참조를 반환할 수 있어
cout << getGradeLabel_1(FRESH) << endl;
cout << getGradeLabel_2(FRESH) << endl; // 얜 출력안되던데
cout << getGradeLabel_3(FRESH) << endl;
int binarySearch(const vector<int>& numbers, int min, int max, int target) {
int mid = (min + max) / 2;
if(min >= max) {
return -1; // 없다
}
if(numbers[mid] == target) {
return mid;
} else if(target < numbers[mid]) {
return binarySearch(numbers, min, mid-1, target);
} else {
return binarySearch(numbers, mid+1, max, target);
}
}
당연히 종료조건 잘정하는게 중요하지
int data[] = {1,3,5,8,20,30};
vector<int> numbers(data, data+sizeof(data)/sizeof(int));
cout << binarySearch(numbers, 0, numbers.size() - 1, 50) << endl; // 이분탐색 -> 정렬해야 가능
long factorial(const int number) {
assert(number >= 0); // 재귀함수의 무한반복을 막아
if(number == 1) {
return 1;
}
return number * factorial(number - 1);
}
int number1 = -2;
const long result = factorial(number1);
cout << "Factorial of " << number1 << " : " << result << endl;
assert로 미리 막는거지 재귀 못하게
cf. binary search -> 반복문 사용
int binarySearch(const vector<int>& numbers, int min, int max, const int target) {
while(max>min) {
const int mid = (min + max) / 2;
if(numbers[mid] == target) {
return mid;
}
if (min >= max) {
return - 1;
}
if(target < numbers[mid]) {
max = mid - 1;
} else {
min = mid + 1;
}
}
return -1;
}
이분탐색 -> 정렬해야 가능
int (fp)(int, int)
반환타입 (변수이름)(매개변수)
int (*functionPointer)() = A; // A함수의 포인터
functionPointer = B; // 그 포인터가 B를 가리키게
int functionPointer(int n) {
cout << n << endl;
return n*n;
}
int (*pFunc)(int) = functionPointer;
// std::function<int(int)> pFunc = f;
int v = pFunc(7);
cout << "v = " << v << endl;
void Sort(int* arr, int size, bool(*compare)(int, int)) {
for(int i=0; i<size-1; i++) {
for(int j=i+1; j<size; j++) {
if(compare(arr[i], arr[j])) {
swap(arr[i], arr[j]);
}
}
}
}
bool asc(int a, int b) { return a > b; }
bool desc(int a, int b) { return a < b; }
int arr[3] { 2, 1, 3};
Sort(arr, 3, asc);
Sort(arr, 3, desc);
// 1) 함수 객체
Multiply multiply;
cout << "함수 객체 " << multiply(10, 2) << endl;
// 2) 람다
auto lambdaMultiply = [](int x, int y) {
return x * y;
};
cout << "람다식 " << lambdaMultiply(10, 2) << endl;
람다 함수, 익명 함수
[] (매개변수) {
함수 동작
}(호출 할 때 인자)
[](int a, int b) {
cout << "lambda: " << a+b << endl;
}(30, 40);
int result1 = 1, result2 = 2, result3 = 3, result4 = 4;
[result1, result2](int a, int b) {
cout << result1 + a + b << endl;
}(10, 20); // <- a = 10, b = 20
[&result3, &result4](int a, int b) {
result3 = 22;
result4 = a + b;
cout << result3 + result4 << endl;
}(10, 20);
auto를 이용해서 람다함수를 -> 변수로
1.
auto func1 = [](int a, int b) {
return a * b;
};
cout << "func1 " << func1(2, 10) << endl;
int num = 20;
auto func2 = [&num](int a) {
num += a;
};
func2(100);
cout << "num: " << num << endl;
cout << "람다 함수 예외 처리" << endl;
auto divide = [](double a, double b) {
if (b==0.0) {
throw invalid_argument("Divisor cannot be zero");
}
return a / b;
};
try {
double result = divide(5.0, 0.0);
} catch (const invalid_argument& e) {
cerr << e.what() << endl;
}
function<void(int, int)> func = Test;
Apple a;
function<void(Apple&, int, int)> func1 = &Apple::Shout; // -> Shout을 함수 포인터로 생성
func1(a,1,2);
a.Shout(1, 2);
=> Shout 함수 포인터 -> func1 함수 포인터에 대입해서
=> 이제 func1의 이름으로도 Apple::Shout 쓸 수 잇음
bind: 함수 포인터에서 매개변수를 고정
반환값은 function!!!!!!!!!!!!!!
특정 인수에 대해서만 함수를 실행시키고 싶을 때, 특정 인수와 특정 함수를 묶어줌
=> 파라미터의 자료형으로부터 자유로워진다!
function<int(int)> func2 = bind(Test, placeholders::_1, 2);
func2(3); // 5