// async : 즉시 실행auto a1 = std::async(std::launch::async, foo);// 이 때 스레드 실행
std::cout<<a1.get();//deferred : 리턴값을 받아올 때 실행auto a1 = std::async(std::launch::deferred, foo);
std::cout<<a1.get();// 이 때 스레드 실행
정책
async : 새로운 스레드를 즉시 실행
deferred : 리턴값을 받아올 때 실행
thread와의 차이점
직접 스레드를 관리(생성, 삭제) 하지 않음
함수에서 던진 예외에 대해 예외처리 가능
oversubscription
스레드는 너무 많은 스레드 만들면 중단
내부적으로 task관리해주기 때문에 중단 없음
스레드를 직접 만들지 않고 스레드 풀 이용
반환값을 받을 수 있다.
future<int> a1 =async(launch::async, foo);constint ret = a1.get();
std::vector<std::unique_ptr<A>> vec;
std::unique_ptr<A>pa(newA(1));//1. 복사 생성자가 없기 때문에 오류 발생!
vec.push_back(pa);//2. 소유권을 이전하면서 vector에 추가
vec.push_back(std::move(pa));//3. emplace_back 사용 시 생성하면서 컨테이너에 넣을 수 있음
vec.emplace_back(newA(1));
주로 멤버 변수가 포인터일 경우 사용
3. shared_ptr
Shared ownership
한 오브젝트에 여러 포인터 가능함
Reference count를 계산하여, 아무도 가리키지 않을 때 자동으로 메모리 해제
생성 방법
shared_ptr<Cat> catPtr = make_shared<Cat>()
자원을 할당 시 주의 사항
자원을 먼저 할당하고 shared_ptr 생성자 인자로 주소값을 전달하지 않도록 하자!
A* a =newA();// 2개의 shared_ptr 객체가 각각 따로 제어블록을 생성함// 참조계수가 각각 1을 가짐
std::shared_ptr<A>pa1(a);
std::shared_ptr<A>pa2(a);
std::string a ="abc";
std::string b = std::move(a);
a 는 L value
"abc" 는 R value
한 번 불려지고 다음에 사용 안함
std::move(L value)
L value를 R value로 변경해줌
a가 가리키던 "abc"가 b로 이동하고 a는 빈값 저장됨
예시
// 값 전달 : 2번 복사voidstoreByValue(string s){
string b = s;}// L value 전달 : 1번 복사voidstoreByLRef(string& s){
string b = s;}// R value 전달 : 0번 복사voidstoreByRRref(string &&s){
string b = std::move(s);}
Animal 포인터로 lion 가리키면 Lion VT의 offset 정보를 가지고 있음(16바이트 전에 Lion의 시작점이 있다.)
thunk 함수를 통해 Lion::speak 함수 호출 가능
thunk 함수는 offset을 계산한 Lion::speak 함수를 가리킴
Lion 포인터로 Lion 가리키면 그냥 호출 가능
15. 템플릿
함수 템플릿 사용 방법
// 1. 생성template<typenameT>
T Add(T num1, T num2){}// 2. 사용
Add<int>(3,4);// int형
Add<int>(3,5,4.5);// double형
typename 대신 class 사용 가능
template<classT>
컴파일 때 입력된 자료형에 맞게 함수가 생성됨
최초 1회 생성, 이후는 생성된 함수 사용
컴파일 속도가 약간 느려짐
용어 정리
함수 템플릿 : 함수를 만드는 템플릿 정의
템플릿 함수 : 템플릿에 의해 생성된 함수
일반 함수가 정의되어 있으면, 템플릿 함수보다 우선 호출됨
템플릿 타입 여러 개 적용 가능
template<classT1,classT2>voidShowData(T1 num1, T2 num2)// 사용
ShowData<int,double>(65,3.6)// int, double형}
함수 템플릿의 특수화
특정 인자로 들어오면 명시적으로 특정 함수를 사용하게 정의 하는 것
ex) Max함수에서 문자가 들어오면 길이 비교
template<>char* Max<char*>(char* a,char* b){returnstrlen(a)>strlen(b)? a : b;}
클래스 템플릿
//1. 선언template<typenameT>classPoint{
T xpos, ypos;public:Point(T x, T y):xpos(x),ypos(y){}};// 사용
Point<int>pos(1,2);//int형 Point 객체
Point<double>pos(1.1,3.1)// double형
// 예외를 던지는 함수voidDivide(int num1,int num2){if(num2 ==0)
trhow num2;}// 함수를 콜하는 부분// Divide 함수 수행 하다 예외 발생시// 아래 catch 부분에서 예외 처리 가능try{Divide(num1, num2);}catch(int expn){...}
함수 선언시 throw 키워드 추가
예외 발생이 있다면 throw 키워드를 꼭 붙여야함!
intFunc(int num)throw(int,char)// int와 char 형식의 예외 발생이 가능하다!// 이 함수 사용시 try catch문이 필요하다고 알림
클래스 형태로 예외 정의 가능
예외 클래스를 정의
예외 클래스는 exception 클래스를 상속!
voiddeposit(money){if( money <0){//expn 예외 객체 생성 및 throw 발생
DepositException expn(money);throw expn;}}try{deposit(-200);}catch( DepositException &expn){
expn.showError();}
17. C++ 형변환 연산자
dynamic_cast(expr)
상속 관계에서 안전한 형 변환 가능
T에 객체는 포인터 또는 참조형 가능
실행시간에 형변환 되므로 속도 느림
static_cast(expr)
C스타일의 형변환 연산자 대신 사용
컴파일 시간에 형변환 되므로 속도 빠름
설계 잘되어 있다면 dynamic 대신 static 사용
const_cast(expr)
참조자의 const 성향을 제거하는 형변환
주로 인자 전달시 불일치 제거를 위해 사용
reinterpret_cast(expr)
전혀 상관이 없는 형 변환에 사용
18. 함수 포인터
정적 함수 호출
일반 함수나 static 멤버 함수를 가리키는 포인터
선언
// 선언void(*pFunc)(int);// 반환값이 void이고 인자가 int형 하나인 함수를 가리킬 수 있는 함수 포인터
멤버 함수 호출
선언
void(Point::*pFunc)();// 반환값이 void이고 인자가 없는 Point 멤버 함수를 가리킬 수 있는 함수 포인터 선언//사용
Point pt;(pt.*pFunc)();// 객체로 사용
Point *p;(p->*pFunc)();// 주소로 사용
print 함수 구현시 ostream&을 인자로 사용하면, 상속 구조에 따라 ostreamstream, ofstream도 사용 가능
//사용 1. coutprint(cout)=> 화면에 결과 출력
//사용 2. fstream
ofstream ofs{"test.txt"};print(ofs)=> 파일에 결과 쓰기
//사용 3. stringstream
stringstream ss;print(ss)=> string에 쓰기