해당 과제를 진행하는데 있어 필요한 사전 지식들을 정리하였습니다.
C++는 다음의 4가지 타입 캐스트 연산자를 지원한다.
1) static_cast
논리적으로 변환 가능한 경우에만 변환 허용
실수 → 정수
또는 정수 → 실수
로 변환하는 것은 가능포인터 → 정수
등으로 변환하는 것은 불가능배열 → 포인터
로 변환하는 것은 가능포인터 type을 다른 것으로 변환하는 것은 허용하지 않지만, 상속 관계에 있어서는 포인터끼리 변환 가능
2) dynamic_cast
포인터 → 포인터
, 참조자 → 참조자
간의 변환만을 허용3) const_cast
volatile
이나 _unaligned
의 속성 처리할 때도 사용 가능4) reinterpret_cast
형식
4가지中1_cast<바꾸려고 하는 type>(대상)
헤더 파일 : <cctype>
int tolower(int c)
, int toupper(int c)
tolower()
는 대문자 → 소문자
, toupper()
는 소문자 → 대문자
, 다른 모든 문자는 그대로 반환하는 함수이다.
헤더 파일 : <iomanip>
1) std::setw(int n)
n
만큼 공간을 확보하고 뒤에서부터 문자를 출력2) std::setfill(char c)
c
로 채워줌3) std::left()
4) std::right()
헤더 파일 : <string>
1) size_t size() const
2) size_t length() const
size()
함수와 같음3) bool empty() const
4) string substr(size_t index = 0, size_t len = npos)const
index
에서부터 len
만큼 잘라서 반환len
의 default npos
는 -1
을 의미헤더 파일 : <sstream>
std::stringstream()
\n
을 제외하고 문자열에서 맞는 자료형의 정보들을 빼냄
Static 멤버 변수란 객체 별로 각각 할당되는 멤버 변수가 아니라 모든 객체가 한 메모리를 공유하는 멤버 변수이다.
객체 생성 전에도 메모리에 존재하기 때문에 객체 생성 전에 반드시 미리 초기화를 해주어야 한다. 모든 객체가 공유해야 하므로 프로그램 전체 영역에서 메모리가 유지되어야 한다. 따라서 반드시 전역 범위에서 정의 및 초기화를 해주어야 한다. 정의 및 초기화는 헤더 파일 내에서는 불가능하기 때문에 .cpp
파일에서 초기화 해주어야 한다. 클래스 내부에서는 초기화가 불가능하므로 private
이더라도 클래스 외부에서 정의가 가능하다.
객체와는 독립적으로 존재하기 때문에 객체 이름으로도 접근이 가능하지만 클래스 이름으로도 접근이 가능하다.
자료형_이름 클래스_이름::static 변수_이름 = 초기화_값
모든 객체들이 알고 있고 공유할 수 있어야 하는 멤버 변수를 static
으로 선언한다.
static const
멤버 변수는 const
이므로 값을 변경하는 것이 불가능하기 때문에 클래스 내에서 초기화 하는 것이 가능하다. 따라서 헤더 파일 내에서도 초기화가 가능하다.
C++에서는 모든 멤버 변수, 함수가 자신만의 this 포인터
를 가지고 있는데 static(정적) 멤버 변수, 함수는 this 포인터
를 가지지 않는다.
char buf[18];
time_t curtime;
struct tm *timeinfo;
time(&curtime);
timeinfo = localtime(&curtime);
strftime(buf, 18, "[%Y%m%d_%H%M%S]", timeinfo);
std::cout << buf << ' ';
헤더 파일 : <ctime>
1) time_t time(time_t *seconds)
2) struct tm *localtime(const time_t *timer)
time()
함수 결과로 나온 초 값을 보기 쉽게 계산해 tm 구조체
형식으로 반환struct tm 구조체
struct tm {
int tm_sec; // 초, range 0 to 59
int tm_min; // 분, range 0 to 59
int tm_hour; // 시간, range 0 to 23
int tm_mday; // 일, range 1 to 31
int tm_mon; // 월, range 0 to 11
int tm_year; // 1900년 부터의 년
int tm_wday; // 요일, range 일(0) to 토(6)
int tm_yday; // 1년 중 경과 일, range 0 to 365
int tm_isdst; // 섬머타임 실시 여부 (양수, 0, 음수)
};
3) size_t strftime(char *ptr, size_t maxsize, const char *format, const struct tm *timeptr)
format
에 들어있는 형식에 맞추어 timeptr
이 가리키는 tm 구조체
의 값을 해석하여 현재 시간을 ptr
이 가리키는 배열에 저장maxsize
표준 템플릿 라이브러리라고 불리는 STL(Standard Template Libaray)은 자료와 알고리즘을 효율적으로 관리할 수 있도록 C++에서 제공하는 표준 라이브러리이다.
STL은 다음과 같은 구성 요소로 이루어진 템플릿을 제공한다.
1) 컨테이너 (container)
컨테이너는 어떤 종류의 객체 컬렉션을 관리하는데 사용된다. 배열이나 연결리스트 형태로 구현되어지는 여러 형태의 컨테이너가 지원된다.
컨테이너를 크게 두 가지로 나누면 순차(sequence) 컨테이너, 연관(associative) 컨테이너로 나눌 수 있다.
순차 컨테이너는 모든 요소들을 선형적인 순차열로 저장하는 형태이다. 원소들이 규칙에 따라 저장한 순서대로 배열된다. 대표적인 예로 벡터(vector), 데큐(deque), 리스트(list)가 있다.
std::vector : 벡터 객체는 요소가 추가되거나 삭제될 때마다 자동으로 메모리를 재할당하여 크기를 동적으로 변경하는 배열이다.
헤더 파일 :<vector>
선언 :vector<data_type> 변수이름
std::pair :
<
와>
로 묶인 2개의 템플릿 인자를 타입으로 하여,first
와second
를 갖는다.
연관 컨테이너는 키(key)와 값(value) 쌍처럼 연관된 데이터를 하나의 쌍 형태로 저장한다. 대표적인 예로 세트(set), 멀티세트(multiset), 맵(map), 멀티맵(multimap)이 있다.
이런 컨테이너 상에서 원소에 접근하는 방법으로는 크게 두 가지가 있는데 하나는 직접 함수를 호출하는 것이고 하나는 반복자(iterator)를 사용하는 것이다.
2) 반복자 (iterator)
반복자는 요소들의 위치와 연관된 동작을 하는 객체이다. 포인터와 개념이 흡사하며 컨테이너에서 어떤 요소의 위치를 나타낸다.
이런 반복자가 있는 이유는 컨테이너와 알고리즘이 하나로 동작하게 묶어주기 때문이다. 컨테이너의 요소들을 가지고 각종 연산을 하기 때문에 반복자가 없다면 특정 컨테이너에만 종속적이게 될 수 있다. 반복자를 이용해서 모든 컨테이너에 결합하여 동작할 수 있도록 해주는 것이다.
연산자 | 기능 |
---|---|
* | 포인터와 동일하게 참조연산 가능 |
++ , -- | 가리키는 요소 주변 요소로 증감연산 가능 |
== , != | 반복자가 같은 위치를 가리키는지 비교연산 가능 |
= | 반복자 간의 대입연산 가능 |
3) 알고리즘 (algorithm)
알고리즘 라이브러리는 컨테이너에 반복자들을 가지고 이런 저런 작업을 쉽게 수행할 수 있도록 도와주는 라이브러리이다.
<algorithm>
라이브러리는 min_element
, max_element
, find
, sort
, for_each
등의 원소들에 대해 작업할 수 있는 여러가지 함수들을 지원한다.
그 중, for_each(InputIterator first, InputIterator last, Function fn)
함수는 범위 내 (first 부터 last 전 까지) 원소들 각각에 대해 함수 fn 을 실행한다. 참고로 함수의 리턴값은 무시된다.
함수를 호출하는 방식은 다음과 같이 세 가지 경우가 있다.
f(x) // f가 멤버함수가 아닌 경우
x->f() // f는 멤버함수이고, x가 포인터
x.f() // f는 멤버함수이고, x가 객체 혹은 참조
for_each
와 같은 알고리즘들에 전달되는 함수는 보편적으로 f(x)
형태를 사용한다. 따라서 x->f()
, x.f()
형태의 함수는 f(x)
형태로 바꾸어주어야 한다. x->f()
와 같은 포인터의 멤버함수를 전달하는 형태는 std::mem_fun
템플릿을 통해, x.f()
와 같은 객체나 참조인 경우는 std::mem_fun_ref
템플릿을 통해 f(x)
형태로 바꾼 상태로 알고리즘에 전달되어야 한다.
std::mem_fun
와 std::mem_fun_ref
를 사용하기 위해서는 <functional>
헤더파일을 포함해주어야 한다.
코드 작성 완료 후 출력 결과를 subject에서 주어지는 .log
와 비교해봤을 때 소멸자 호출 순서가 다를 수도 있다. Account
클래스 0 ~ 7번을 추가했을 때, 소멸 시 0 ~ 7 순서로 소멸될 수도 있고 그 역순으로 소멸 될 수도 있다.
이는 OS마다 소멸 순서가 약간 다를 수 있기 때문에 굳이 순서를 맞추려고 하는 행위는 무의미하다. Mac OS
같은 경우는 0 ~ 7번을 추가했을 때 이의 역순으로 소멸하고, Ubuntu
의 경우에는 0 ~ 7번을 추가했을 때 해당 순서를 그래도 유지하며 소멸된다. 이와 같이 시스템마다 소멸 순서가 다른 이유는 std::vector
의 소멸자 구현이 시스템마다 다르기 때문이다.
참고
https://blockdmask.tistory.com/236?category=249379
https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=psychoria&logNo=40127510679
https://blockdmask.tistory.com/477
https://life-with-coding.tistory.com/403
https://blockdmask.tistory.com/338
https://ansohxxn.github.io/cpp/chapter8-10/
https://jhnyang.tistory.com/305
https://modoocode.com/122
https://blog.naver.com/vjhh0712v/221569740879
https://modoocode.com/260
https://ifyouwanna.tistory.com/entry/memfun-%EC%99%80-memfunref-%EB%A5%BC-%EC%9D%B4%EC%9A%A9%ED%95%9C-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98%EC%97%90-%EB%A9%A4%EB%B2%84%ED%95%A8%EC%88%98-%EC%A0%84%EB%8B%AC
https://bigpel66.oopy.io/library/42/inner-circle/11