반응형
반응형

1. list 컨테이너

1.1 list의 주요 특징

  1. 원소가 노드 단위로 저장

  2. list는 이중 연결 리스트로 구현

  3. 앞/뒤 원소 추가/제거 가능

  4. 임의 접근 반복자가 아닌 양방향 반복자

    • 원소 탐색을 위해 ++ 또는 -- 사용
    • at, [] 연산자 없음
  5. 중간에 원소 추가 제거 시 효율적

    • vector, deque와 다르게 노드만 연결/삭제
  6. 다른 리스트와 결합이 용이함

  7. 템플릿 형식

    • T 는 list 컨테이너 원소의 형식
template<typename T, typename Allocator = allocator<T>>
class list

 

  1. 생성자

    코드 내용
    list lt lt는 빈 컨테이너
    list lt(n) lt는 기본값으로 초기화된 n개의 원소 가짐
    list lt(n, x) lt는 x값으로 초기화된 n개의 원소 가짐
    list lt(lt2) lt는 lt2컨테이너의 복사본(복사 생성자 호출)
    list lt(b,e) lt는 반복자 구간 [b,e)로 초기화된 원소 가짐

 

  1. 멤버 함수

    코드 내용
    lt.assign(n,x) lt에 x값으로 n개의 원소를 할당
    lt.assign(b,e) lt를 반복자 구간 [b,e)로 할당
    lt.front() lt의 첫 번째 원소 참조
    lt.back() lt의 마지막 원소 참조
    p=lt.begin() p는 lt의 첫원소를 가리키는 반복자
    p=lt.end() p는 lt의 끝을 나타내는 반복자
    lt.clear() lt의 모든 원소 제거
    lt.empty() lt가 비었는지 조사
    q=lt.erase(p) p가 가리키는 원소 제거(q는 다음 원소 가리킴)
    q=lt.erase(b,e) 반복자 구간[b,e)의 모든 원소를 제거(q는 다음 원소)
    q=lt.insert(p,x) p가 가리키는 위치에 x값 삽입(q는 삽입한 원소 가리킴)
    lt.insert(p,n,x) p가 가리키는 위치에 n개의 x값 삽입
    lt.insert(p,b,e) p가 가리키는 위치에 반복자 구간[b,e)의 원소를 삽입
    x=lt.max_size() x는 lt가 담을 수 있는 최대 원소 개수(메모리 크기)
    lt.merge(lt2) lt2를 lt로 합병 정렬(오름차순 : less)
    lt.merge(lt2, pred) lt2를 lt로 합병 정렬(pred를 기준으로 합병)
    lt.pop_back() lt의 마지막 원소 제거
    lt.pop_front() lt의 첫 원소 제거
    lt.push_back(x) lt의 끝에 x 추가
    lt.push_front(x) lt의 앞에 x 추가
    p=lt.rbegin() p는 lt의 역 순차열의 첫 원소를 가리키는 반복자
    p=lt.rend() p는 lt의 역 순차열의 끝을 표식하는 반복자
    lt.remove(x) x 원소를 모두 제거
    lt.remove_if(pred) pred(단항조건자)가 참인 모든 원소 제거
    lt.resize(n) lt의 크기를 n으로 변경(크기가 커지면 기본값으로 초기화)
    lt.resize(n,x) lt의 크기를 n으로 변경(크기가 커지면 x로 초기화)
    lt.reverse() lt 순차열을 뒤집음
    lt.size() lt 원소의 개수
    lt.sort() lt의 모든 원소를 오름차순으로 정렬
    lt.sort(pred) lt의 모든 원소를 pred를 기준으로 정렬
    lt.splice(p, lt2) p가 가리키는 위치에 lt2의 모든 원소를 잘라 붙임
    lt.splice(p, lt2, q) p가 가리키는 위치에 lt2의 q가 가리키는 원소를 잘라 붙임
    lt.splice(p, lt2, b, e) p가 가리키는 위치에 lt2의 순차열 [b,e)를 잘라 붙임
    lt.swap(lt2) lt와 lt2를 swap
    lt.unique() 인접한 원소의 값이 같다면 유일한 원소의 순차열로 만듦
    lt.unique(pred) 인접한 원소가 pred(이항 조건자)의 기준에 맞다면 유일한 원소의 순차열로 만듦

 

  1. 연산자

    코드 내용
    lt1==lt2 lt1과 lt2의 모든 원소가 같은가?
    lt1!=lt2 lt1과 lt2의 원소중 하나라도 다른가?
    lt1 < lt2 문자열 비교처럼 lt2가 lt1보다 큰가?

 

  1. 멤버 형식

코드 내용
allocator_type 메모리 관리자 형식
const_iterator const 반복자 형식
const_pointer const value_type* 형식
const_reference const value_type& 형식
const _reverse_iterator const 역 반복자 형식
difference_type 두 반복자 차이의 형식
iterator 반복자 형식
pointer value_type* 형식
reference value_type& 형식
reverse_iterator 역 반복자 형식
size_type 첨자(index)나 원소의 개수 등의 형식
value_type 원소의 형식

2 상세 내용

  1. lt.remove(10)

    • 원소값 10을 가지는 모든 노드 찾아 삭제
    • 값기반 삭제는 list만 보유

 

  1. lt.remove_if(Pred)

    • 모든 원소에 Pred 함수 적용하여 참인 원소 삭제

 

  1. lt1.splice(iter, lt2)

    • iter위치에 lt2의 모든 원소를 lt1에 잘라 붙임
    • 노드를 연결만 하기 때문에 속도 빠름

 

  1. lt1.splice(iter, lt2, iter2)

    • iter 위치에 iter2가 가리키는 lt2 원소 붙임

 

  1. lt1.splice(lt1.end(), lt2, lt2,begin(), lt2.end())

    • lt1의 끝에 lt2를 잘라 붙임

 

  1. lt.unique()

    • 인접한 중복 원소를 하나만 남기고 삭제

 

  1. lt.unique(Pred)

    • Pred(이항 조건자)가 참이면 원소 삭제
    • Ex)
bool Pred(int first, int second){
   return second - first <= 0;
}
// 뒤의 원소가 현재 원소보다 작거나 같으면 삭제

 

  1. 정렬

    • 알고리즘의 sort는 임의 접근 반복자 지원
    • vector와 deque는 알고리즘 사용하여 정렬 가능
    • 리스트는 양방향 접근 반복자여서 알고리즘 sort 사용 못함
    • 리스트는 멤버 함수로 sort 함수 지원
    • lt.sort() : 오름차순 정렬
    • lt.sort(greater<int>()) : 내림 차순 정렬

 

  1. lt1.merge(lt2)

    • lt2를 lt1에 합병 정렬
    • 정렬 기준은 less(오름차순)
    • 합병할 리스트가 정렬 안되어 있으면 오류 발생
    • lt1과 lt2의 정렬 기준 다르면 오류 발생
    • Ex) lt1 = {10,20,30,40,50}
    • lt2 = {25, 35, 60}
    • 합병 정렬 하면
    • lt1 = {10,20,25,30,35,40,50,60}

참고

뇌를 자극하는 C++ STL

반응형

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

[STL-06] 알고리즘1-원소를 수정하지 않는 알고리즘  (0) 2021.03.14
[STL-05] 연관 컨테이너  (0) 2021.03.14
[STL-03] 시퀀스 컨테이너2- deque  (0) 2021.03.11
[STL-02] 시퀀스 컨테이너1- vector  (0) 2021.03.11
[STL-01] 소개  (0) 2021.03.11
반응형

1. deque 컨테이너

  1. 벡터와의 차이

    • 여러 개의 메모리 블록을 할당
    • 사용자에게는 하나의 블록처럼 보이게 함 -원소 추가시 메모리 부족해도 이전 메모리 제거 및 원소 복사 안함

 

  1. deque의 주요 특징

    • 여러 메모리 블록에 나뉘어 원소 저장
    • 앞/뒤 모두 원소 추가/제거 가능
    • vector보다 원소 추가/제거 시에 성능 효율적

 

  1. 템플릿 형식

    • T 는 deque 컨테이너 원소의 형식
template<typename T, typename Allocator = allocator<T>>
class deque

 

  1. 생성자

    코드 내용
    deque dq dq는 빈 컨테이너
    deque dq(n) dq는 기본값으로 초기화된 n개의 원소 가짐
    deque dq(n, x) dq는 x값으로 초기화된 n개의 원소 가짐
    deque dq(dq2) dq는 dq2컨테이너의 복사본(복사 생성자 호출)
    deque dq(b,e) dq는 반복자 구간 [b,e)로 초기화된 원소 가짐

 

  1. 멤버 함수

    코드 내용
    dq.assign(n,x) dq에 x값으로 n개의 원소를 할당
    dq.assign(b,e) dq를 반복자 구간 [b,e)로 할당
    dq.at(i) dq의 i번째 원소를 참조
    dq.front() dq의 첫 번째 원소 참조
    dq.back() dq의 마지막 원소 참조
    p=dq.begin() p는 dq의 첫원소를 가리키는 반복자
    p=dq.end() p는 dq의 끝을 나타내는 반복자
    dq.clear() dq의 모든 원소 제거
    dq.empty() dq가 비었는지 조사
    q=dq.erase(p) p가 가리키는 원소 제거(q는 다음 원소 가리킴)
    q=dq.erase(b,e) 반복자 구간[b,e)의 모든 원소를 제거(q는 다음 원소)
    q=dq.insert(p.x) dq가 가리키는 위치에 x값 삽입(q는 삽입한 원소 가리킴)
    dq.insert(p,n,x) p가 가리키는 위치이 n개의 x값 삽입
    dq.insert(p,b,e) p가 가리키는 위치에 반복자 구간[b,e)의 원소를 삽입
    x=dq.max_size() x는 dq가 담을 수 있는 최대 원소 개수(메모리 크기)
    dq.pop_back() dq의 마지막 원소 제거
    dq.pop_front() dq의 첫 원소 제거
    dq.push_back(x) dq의 끝에 x 추가
    dq.push_front(x) dq의 앞에 x 추가
    p=dq.rbegin() p는 dq의 역 순차열의 첫 원소를 가리키는 반복자
    p=dq.rend() p는 dq의 역 순차열의 끝을 표식하는 반복자
    dq.resize(n) dq의 크기를 n으로 변경(크기가 커지면 기본값으로 초기화)
    dq.resize(n,x) dq의 크기를 n으로 변경(크기가 커지면 x로 초기화)
    dq.size() dq 원소의 개수
    dq.swap(dq2) dq와 dq2를 swap

 

  1. 연산자

    코드 내용
    dq1==dq2 dq1과 dq2의 모든 원소가 같은가?
    dq1!=dq2 dq1과 dq2의 원소중 하나라도 다른가?
    dq1 < dq2 문자열 비교처럼 dq2가 dq1보다 큰가?
    dq[i] dq의 i 번째 원소를 참조

 

  1. 멤버 형식

    코드 내용
    allocator_type 메모리 관리자 형식
    const_iterator const 반복자 형식
    const_pointer const value_type* 형식
    const_reference const value_type& 형식
    const _reverse_iterator const 역 반복자 형식
    difference_type 두 반복자 차이의 형식
    iterator 반복자 형식
    pointer value_type* 형식
    reference value_type& 형식
    reverse_iterator 역 반복자 형식
    size_type 첨자(index)나 원소의 개수 등의 형식
    value_type 원소의 형식

2 상세 내용

  1. dq.push_front(100)
    • deque 앞에 100을 원소로 추가

 

  1. 삽입 제거 사용 방법 벡터와 동일
    • vector 보다 효율적으로 동작
    • 삽입, 제거 시 원소가 적은 쪽으로 밀어냄
    • ex)10, 20, 30, 40, 50, 60 원소
    • 30의 위치에 50을 추가시에
    • 앞쪽으로 밀어냄

참고

뇌를 자극하는 C++ STL

반응형

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

[STL-06] 알고리즘1-원소를 수정하지 않는 알고리즘  (0) 2021.03.14
[STL-05] 연관 컨테이너  (0) 2021.03.14
[STL-04] 시퀀스 컨테이너3- list  (0) 2021.03.12
[STL-02] 시퀀스 컨테이너1- vector  (0) 2021.03.11
[STL-01] 소개  (0) 2021.03.11
반응형

1. Vector 컨테이너

  1. 템플릿 형식
    • T 는 vector 컨테이너 원소의 형식
template<typename T, typename Allocator = allocator<T>>
class vector
  1. vector의 주요 특징

    • 원소가 메모리 블록에 연속하게 저장됨
    • 조회 속도는 빠름
    • insert, erase 느림

 

  1. 생성자

    코드 내용
    vector v v는 빈 컨테이너
    vector v(n) v는 기본값으로 초기화된 n개의 원소 가짐
    vector v(n, x) v는 x값으로 초기화된 n개의 원소 가짐
    vector v(v2) v는 v2컨테이너의 복사본(복사 생성자 호출)
    vector v(b,e) v는 반복자 구간 [b,e)로 초기화된 원소 가짐

 

  1. 멤버 함수

    코드 내용
    v.assign(n,x) v에 x값으로 n개의 원소를 할당
    v.assign(b,e) v를 반복자 구간 [b,e)로 할당
    v.at(i) v의 i번째 원소를 참조
    v.front() v의 첫 번째 원소 참조
    v.back() v의 마지막 원소 참조
    p=v.begin() p는 v의 첫원소를 가리키는 반복자
    p=v.end() p는 v의 끝을 나타내는 반복자
    x=v.capacity() x는 v에 할당된 공간의 크기
    v.clear() v의 모든 원소 제거(할당된 공간은 유지)
    v.empty() v가 비었는지 조사
    q=v.erase(p) p가 가리키는 원소 제거(q는 다음 원소 가리킴)
    q=v.insert(p.x) p가 가리키는 위치에 x값 삽입(q는 삽입한 원소 가리킴)
    v.insert(p,n,x) p가 가리키는 위치이 n개의 x값 삽입
    v.insert(p,b,e) p가 가리키는 위치에 반복자 구간[b,e)의 원소를 삽입
    x=v.max_size() x는 v가 담을 수 있는 최대 원소 개수(메모리 크기)
    v.pop_back() v의 마지막 원소 제거
    v.push_back(x) v의 끝에 x 추가
    p=v.rbegin() p는 v의 역 순차열의 첫 원소를 가리키는 반복자
    p=v.rend() p는 v의 역 순차열의 끝을 표식하는 반복자
    v.reserve(n) n개의 원소를 저장할 공간 예약
    v.resize(n) v의 크기를 n으로 변경(크기가 커지면 기본값으로 초기화)
    v.resize(n,x) v의 크기를 n으로 변경(크기가 커지면 x로 초기화)
    v.size() v 원소의 개수
    v.swap(v2) v와 v2를 swap

 

  1. 연산자

    코드 내용
    v1==v2 v1과 v2의 모든 원소가 같은가?
    v1!=v2 v1과 v2의 원소중 하나라도 다른가?
    v1 < v2 문자열 비교처럼 v2가 v1보다 큰가?
    v[i] v의 i 번째 원소를 참조

 

  1. 멤버 형식

코드 내용
allocator_type 메모리 관리자 형식
const_iterator const 반복자 형식
const_pointer const value_type* 형식
const_reference const value_type& 형식
const_ reverse_iterator const 역 반복자 형식
difference_type 두 반복자 차이의 형식
iterator 반복자 형식
pointer value_type* 형식
reference value_type& 형식
reverse_iterator 역 반복자 형식
size_type 첨자(index)나 원소의 개수 등의 형식
value_type 원소의 형식

2. 상세 내용

  1. vector::size_type

    • 벡터 사이즈, 첨자를 나태내기 위한 typedef 멤버

 

  1. v.reserve(8)

    • 벡터 메모리 크기 설정
    • capacity 를 8로 설정

 

  1. v.resize(10)

    • 벡터의 사이즈 변경
    • 사이즈가 커지면 capacity 같이 커짐
    • 사이즈 작아지면 capacity는 그대로

 

  1. v.resize(10, 100)

    • size변경 시 크기가 커지면 100으로 초기화

 

  1. v.clear()

    • 벡터 원소 삭제
    • capacity는 그대로

 

  1. vector().swap(v)

    • 벡터 원소 삭제
    • capacity도 0으로 초기화

 

  1. 임의의 원소 참조

    • v.at(0) : 벡터 범위 검사, 안정적, 속도 느림
    • v[0] : 벡터 범위 검사 X, 위험, 속도 빠름

 

  1. v.assign(5,2)

    • 사이즈 5로 변경 및 5 요소에 2로 할당
    • 사이즈가 줄어들면 capacity는 그대로

 

  1. vector::iterator iter

iter = v.begin() // iter를 시작 위치로 설정
(*iter); // 현재 iter 위치의 원소값
iter +=2; // iter의 위치를 2 이동

 

  1. vector::const_iterator citer
    • 원소의 값을 변경하지 않을 때 선언
vector<int>::const_iterator citer
(*citer) = 100 // (X) 값 변경 못함

 

  1. vector::reverse_iterator
    • 역방향 반복자 선언
// 마지막 원소를 가리키는 역방향 반복자 선언
vector<int>::reverse_iterator riter = v.rbegin();

 

  1. iter2 = v.insert(iter, 100)

    • iter 위치에 100을 추가
    • iter2는 추가된 위치를 가리킴

 

  1. v.insert(iter, 3, 100)

    • iter위치에 100값 3개 추가

 

  1. iter2 = v.erase(iter)

    • iter 위치 원소를 삭제
    • iter2는 삭제된 원소 다음 위치

 

  1. iter2 = v.erase(v.begin() + 1, v.end())

    • 시작 원소만 두고 모두 삭제
    • v.end()가 iter2에 저장됨

 

참고

뇌를 자극하는 C++ STL

반응형

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

[STL-06] 알고리즘1-원소를 수정하지 않는 알고리즘  (0) 2021.03.14
[STL-05] 연관 컨테이너  (0) 2021.03.14
[STL-04] 시퀀스 컨테이너3- list  (0) 2021.03.12
[STL-03] 시퀀스 컨테이너2- deque  (0) 2021.03.11
[STL-01] 소개  (0) 2021.03.11
반응형

1.컨테이너

  1. 컨테이너 : 객체를 저장하는 객체

1.1 삽입 순서에 따른 분류

  1. 표준 시퀀스 컨테이너 : 삽입 순서를 가지는 것
    • vector, deque, list 등
  2. 표준 연관 컨테이너 : 삽입 순서 없이 자동 정렬
    • map, set, multiset, multimap 등

1.2 메모리 단위 저장에 따른 분류

  1. 배열 기반 컨테이너 : 연속된 메모리에 저장
    • vector, deque
  2. 노드 기반 컨테이너 : 각 메모리 단위에 저장
    • list, set, multiset, map, multimap

2.반복자

  1. 반복자 : 컨테이너 원소를 순회하고 접근하는 방법
  2. 특징
    • 컨테이너 원소를 가리킨다.
    • 다음 원소로 이동하고 모든 원소를 순회 가능
    • begin()과 end()로 시작과 끝을 가리킴

2.1 반복자의 범주

  1. 입력 반복자
    • 현위치 원소를 한번만 읽는 반복자
    • ex)istream
  2. 출력 반복자
    • 현위치 원소를 한번만 쓰는 반복자
    • ex)ostream
  3. 순방향 반복자
    • 순반향으로 이동 가능한 반복자
  4. 양방향 반복자
    • 순/역방향으로 이동 가능한 반복자
    • ex) list, set, map, multimap, multiset
  5. 임의 접근 반복자
    • +, - , [] 연산이 가능한 반복자
    • ex) vector, deque

3. 알고리즘

  1. 범주
    • 원소를 수정하지 않는 알고리즘
    • 원소를 수정하는 알고리즘
    • 제거 알고리즘
    • 변경 알고리즘
    • 정렬 알고리즘
    • 정렬된 범위 알고리즘
    • 수치 알고리즘

4. 함수 객체

  1. operator()을 오버로딩한 객체

5. 어댑터

  1. 구성요소의 인터페이스를 변경해 새로운 인터페이스를 갖는 요소로 변경

  2. 컨테이너 어댑터

    • stack, queue, priority_queue
  3. 반복자 어댑터

    • reverse _iterator, insert_iterator
    • back _insert _iterator, front _insert_iterator
  4. 함수 어댑터

    • 바인더, 부정자, 함수 포인터 어댑터

6. 할당기

  1. 메모리 할당 정보와 정책을 캡슐화 한 것

참고

뇌를 자극하는 C++ STL

반응형
반응형

1. 클로저(C++예시)

2. 람다 expression(C++11 부터)

  1. 람다 표현식이란?

    • 이름이 없는 함수 객체를 만드는 방법

    • 람다 표현식과 Functor(함수 객체)의 어셈블리 코드는 동일함

  2. 형식

    • auto lambda = [localv=3](int a){
      return a + localv;
      }
    • 캡쳐 : [] 안에 들어가는 부분
class Plus{
public:
   explicit Plus(int a) : localVar{a} {}
   int operator() (int x) const{
      return localVar + x;
   }
private:
   int localVar;
}

int main(){
   auto lambdaPlus3 = [localVar=3](int x){
      return localVar + x;
   }

   Plus plus3{3};

   std::cout << plus3(10) << std::endl;
   std::cout << lambdaPlus3(10) << std::endl;
   // 위의 결과 및 어셈블리 코드는 동일함
}

3. 캡쳐

  1. 값에 의한 캡쳐
    • [localv] 또는 [=]
    • 함수 객체의 멤버 변수와 같은 역할
    • [localv] : 위에서 localv 변수를 찾아 람다 내부에서 사용
    • [=] 만 쓰면 람대 내부에 사용된 변수를 위에서 찾아 자동으로 값에 의한 캡쳐를 함
int three{3};
auto lambdaPlus3 = [=](int x){
   return x + three;
// 위에서 three를 찾아 값에 의한 캡쳐를 함
};
  1. 참조에 의한 캡쳐

    • 함수 객체의 참조 멤버 변수와 같은 역할
    • 전달하는 객체가 큰 경우 사용
    • [&] 만 쓸 경우 람대 내부에 사용된 변수를 위에서 찾아 자동으로 참조에 의한 캡쳐를 함
  2. this에 의한 캡쳐

    • [this]
    • 멤버 변수와 함수를 람대 내부에서 사용 가능함!
class Cat{
public:
   explicit Cat(int age) : mAge{age} {}
   void speak() const {}
   void test() const {
      auto lambda = [this](){
         this->mAge;
         this->speak();
      }
      lambda();
   }
private:
   int mAge;

int main(){
   Cat kitty(3);
   kitty.test();
}

4. 람다 표현식 + STL 함수 사용 예제

vector<int> nums{1,2,3,4,5,6,7,8,9,10};
auto lambdaAdd10 = [](int &n){
   n += 10;
}

for_each(nums.begin(), nums.end(), lambdaAdd10);
// nums 의 인자에 모두 10을 더함
// nums = {11, 12, 13, 14, 15, 16, 17, 18, 19, 20}

5. 고차원 함수란

  1. 함수를 인자로 받음
  2. 함수를 리턴함

6. 함수형 프로그래밍

  1. 함수를 변수나 객체처럼 다룰 수 있다.
  2. std::function 사용 시
    • 함수형 포인터, functor, 람다식 모두 가능함
void freeFunc(int num){
   cout << num;
};

void runFunction(
   int num,
   const std::function<void(int)>& fn){
      //function 사용
      fn(i);
   }

int main(){
// 1. 함수 포인터 전달
   void (*fnPtr)(int) = freeFunc;
   runFunction(10, fnPtr);

// 2. 함수 객체 전달
   FunctionObj funcObj;
   runcFunction(10, funcObj);

// 3. 람다식 전달
   auto lambdaFn = [](int num){
      cout << num;
   };
   runFunction(10, lambdaFn);
}

참고

코드없는 프로그래밍(유투브)

반응형

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

[C++]병렬 프로그래밍  (0) 2021.03.11
[C++]스마트 포인터  (0) 2021.03.09
[C++]LR value 및 최적화  (0) 2021.03.09
[C++]빌드 프로세스  (0) 2021.03.09
[C++]메모리 구조  (0) 2021.03.09
반응형

1.async

  • 사용 예시
// 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(); // 이 때 스레드 실행
  1. 정책

    • async : 새로운 스레드를 즉시 실행
    • deferred : 리턴값을 받아올 때 실행
  2. thread와의 차이점

    • 직접 스레드를 관리(생성, 삭제) 하지 않음
    • 함수에서 던진 예외에 대해 예외처리 가능
    • oversubscription
      • 스레드는 너무 많은 스레드 만들면 중단
      • 내부적으로 task관리해주기 때문에 중단 없음
    • 스레드를 직접 만들지 않고 스레드 풀 이용
    • 반환값을 받을 수 있다.
future<int> a1 = async(launch::async, foo);
const int ret = a1.get();

2.OpenMP

  1. 병렬 프로그래밍을 쉽게 할 수 있게 제공하는 API
  2. 사용 방법
    • 헤더 추가 : omp.h
    • 사용 : 부하가 많은 곳 위에 명령 입력
      #pragma omp parallel for
    • fork and join 모델로 컴파일 됨
    • 코어 개수 만큼 스레드 생성
#include <omp.h>
void main(){
   int a[1000];
   int b[1000];
   int c[1000];

   #pragma omp parallel for
   for(int i=0; i< 1000 ; i++){
      c[i] = a[i] + b[i];
   }
}
  1. 옵션
    • 위의 구문 뒤에 옵션 추가 가능

1)schedule(dynamic,1) 옵션

  • 1 = chuncksize, defualt = 1
  • chuncksize 개수만큼 배열을 태크스로 나누고, 코어 개수 만큼 스레드 런칭
  • dynamic하게 태스크를 수행하여, 먼저 끝난 스레드는 다음 태스크를 수행
  • static 옵션은 스레드가 수행할 태크스를 미리 정하고 끝나면 기다리므로 비효율적

참고

코드없는 프로그래밍(유투브)

3.CUDA

  1. 개발 순서
    • 커널(함수) 선언
    • 변수를 할당(cudaMalloc)
    • 변수를 복사(cudaMemcpy)
    • 동작 수행
    • 결과 변수를 복사(cudaMemcpy)
    • 변수 메모리 해제(cudaFree)
__global__
void add(int n, float *x, float *y, float *z){
   int i = blcokIdx.x * blockDim.x + threadIdx.x;
   if( i < n){
      z[i] = x[i] + y[i];
   }
}
void main(){
   int N = 100000;
   std::vector<float> x(N);
   std::vector<float> y(N);
   std::vector<float> z(N);

   float * d_x, *d_y, *d_z;
   cudaMalloc(&d_x, N*sizeof(float));
   cudaMalloc(&d_y, N*sizeof(float));
   cudaMalloc(&d_z, N*sizeof(float));

   cudaMemcpy(d_x, x.data(), N*sizeof(float), cudaMemcpyHostToDevice);
   cudaMemcpy(d_y, y.data(), N*sizeof(float), cudaMemcpyHostToDevice);

   add<<<(N+255)/256, 256>>>(N, d_x, d_y, d_z);

   cudaMemCpy(z.data(), d_z, N*sizeof*float), cudaMemcpyDeviceToHost);

   cudaFree(d_x);
   cudaFree(d_y);
   cudaFree(d_z);
}

4. thread에서 메모리 맵

  1. 로컬 변수(스택 공간)는 각 스레드에 종속적
  2. 힙과 static 공간은 공유함
    • race condition 발생 가능

5.false sharing

  1. 병렬 프로그래밍이 더 느릴 수 있다.
  2. 원인
    • 멀티 코어 환경에서 각 코어에서 접근하고 있는 데이터가 같은 캐시라인에 있을 때 발생
    • 실제 공유 데이터가 아님에도 하드웨어에서는 공유하는 것으로 착각
    • 동기화가 발생하여 속도가 저하됨
  3. 해결 방법

6. condition variable

  1. 한 스레드에서 다른 쓰레드로 신호를 보냄
  2. 신호를 받은 쓰레드는 컨디션 밸류를 체크하고 동작 수행
  3. 컨디션 밸류는 두 쓰레드에서 쓰기 때문에 뮤텍스 필수!
#include <thread>
#include <mutex>
#include <condition_variable>

std::mutex m;
std::condition_variable cv;
int condition = 0;

void foo(){
   std::unique_lock<std::mutex> lock(m);
   cv.wait(lock, []{return condition==1;})
//lock is acquired, mutual exc job
   lock.unlock();
   // do rest jobs;
}
int main(){
   std::thread waitngT(foo);
   {
      std::scoped_lock lock(m);
      condition = 1;
   }
   cv.notify_one();
   waitngT.join();
}

참고

코드없는 프로그래밍(유투브)

반응형

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

[C++] 함수형 프로그래밍  (0) 2021.03.11
[C++]스마트 포인터  (0) 2021.03.09
[C++]LR value 및 최적화  (0) 2021.03.09
[C++]빌드 프로세스  (0) 2021.03.09
[C++]메모리 구조  (0) 2021.03.09
반응형

1. 스마트 포인터란?

  1. 스택의 포인터 변수가 없어질 때 자동 메모리 해제
  2. 종류
    • unique_ptr
    • shared_ptr
    • weak_ptr

2.unique_ptr

  1. exclusive ownership
    • 한 오브젝트에 하나의 포인터만 허용함
  2. 생성 방법
unique_ptr<Cat> catPtr = make_unique<Cat>()
  1. get 함수 또는 연산자를 통해 자원 접근 가능
//operator -> 를 이용해 자원 접근
catPtr->doSomething();

// get함수를 통해 자원 접근
catPtr.get() //포인터를 반환
  1. std::move를 통해 소유권 이전 가능
    • 소유권을 이전한 unique_ptr을 댕글링 포인터(dangling pointer) 라고 함
unique_ptr<Cat> catPtr1 = move(CatPtr)
  1. unique_ptr을 함수 인자로 전달하기
    • unique_ptr은 복사를 수행하지 않기 때문에 함수 인자로 전달 불가
    • unique_ptr에서 관리하는 자원을 직접 전달
void do_something(Cat* ptr) { };
do_something(catPtr.get());
  1. unique_ptr을 원소로 가지는 컨테이너에서 사용 방법
std::vector<std::unique_ptr<A>> vec;
std::unique_ptr<A> pa(new A(1));

//1. 복사 생성자가 없기 때문에 오류 발생!
vec.push_back(pa);

//2. 소유권을 이전하면서 vector에 추가
vec.push_back(std::move(pa));

//3. emplace_back 사용 시 생성하면서 컨테이너에 넣을 수 있음
vec.emplace_back(new A(1));
  1. 주로 멤버 변수가 포인터일 경우 사용

3. shared_ptr

  1. Shared ownership
    • 한 오브젝트에 여러 포인터 가능함
  2. Reference count를 계산하여, 아무도 가리키지 않을 때 자동으로 메모리 해제
  3. 생성 방법
shared_ptr<Cat> catPtr = make_shared<Cat>()
  1. 자원을 할당 시 주의 사항
    • 자원을 먼저 할당하고 shared_ptr 생성자 인자로 주소값을 전달하지 않도록 하자!
A* a = new A();
// 2개의 shared_ptr 객체가 각각 따로 제어블록을 생성함
// 참조계수가 각각 1을 가짐
std::shared_ptr<A> pa1(a);
std::shared_ptr<A> pa2(a);
  1. 클래스에서 this를 사용해 shared_ptr을 만들 때
    • 클래스에서 enable_shared_from_this<A> 를 상속 받음
    • shared _from _this()를 통해 this를 shared_ptr로 만들자!
class A : public std::enable_shared_from_this<A>{
   std::shared_ptr<A> get_shared_ptr() {
      return shared_from_this();
   }
}
  1. 원형 참조가 있으면 여전히 메모리 릭 발생 가능
    • weak_ptr을 통해 해결 가능
class Cat{
public:
   std::shared_ptr<Cat> mFriend;
};

int main(){
   std::shared_ptr<Cat> pKitty = std::make_shared<Cat>();
   std::shared_ptr<Cat> pNabi = std::make_shared<Cat>();

   pKitty->mFriend = pNabi;
   pNabi->mFriend = pKitty;
}

4. weak_ptr

  1. 일반 포인터와 shared_ptr 사이에 위치한 스마트 포인터
  2. 참조하여도 reference count가 증가되지 않음
  3. weak_ptr 자체로는 원래 객체를 참조할 수 없음
    • weak _ptr 생성시 shared _ptr 또는 weak _ptr을 생성자 인자로 받음
    • 일반 포인터 주소값으로 weak_ptr 생성 불가
    • 가리키는 객체가 이미 소멸되었으면, 빈 shared_ptr로 변환
    • 아닐 경우 해당 객체를 가리키는 shared_ptr로 변환
  4. lock 함수를 통해 shared_ptr로 변환
std::weak_ptr<A> other(std::shared_ptr<A>(new A(1)));
std::shared_ptr<A> o = other.lock();

참고

반응형

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

[C++] 함수형 프로그래밍  (0) 2021.03.11
[C++]병렬 프로그래밍  (0) 2021.03.11
[C++]LR value 및 최적화  (0) 2021.03.09
[C++]빌드 프로세스  (0) 2021.03.09
[C++]메모리 구조  (0) 2021.03.09
반응형

1. 값, 포인터, 참조 전달

  1. 어셈블리 코드로 변경하면 포인터, 참조는 동일 형태
  2. 가급적 포인터가 필요한 경우 제외하고 참조 이용
    • const int& 형태로 사용가능하기 때문!
  3. 값으로 전달 시 크기가 커지면 불필요한 공간 사용
    • 참조 전달 사용

2. L value, R value

std::string a = "abc";
std::string b = std::move(a);
  1. a 는 L value
  2. "abc" 는 R value
    • 한 번 불려지고 다음에 사용 안함
  3. std::move(L value)
    • L value를 R value로 변경해줌
    • a가 가리키던 "abc"가 b로 이동하고 a는 빈값 저장됨
  4. 예시
// 값 전달 : 2번 복사
void storeByValue(string s){
    string b = s;
}

// L value 전달 : 1번 복사
void storeByLRef(string& s){
    string b = s;
}

// R value 전달 : 0번 복사
void storeByRRref(string &&s){
    string b = std::move(s);
}
  1. 값에 의한 전달
    • 2번 복사 일어남
  2. L value 전달
    • 1번 복사 일어남
  3. R value 전달
    • 복사 없음

3. 입력값 최적화

  1. 인자는 값에 의한 전달로 구현
  2. 내부에서 std::move로 작성
  3. 결과
    • L value로 넘어오면 1 copy 수행
    • R value로 넘어오면 0 copy 수행

4. RVO(Return Value Optimization)

  1. return by value로 적용
    • RVO 작동하여 0 copy 발생

참고

코드없는 프로그래밍(유투브)

반응형

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

[C++]병렬 프로그래밍  (0) 2021.03.11
[C++]스마트 포인터  (0) 2021.03.09
[C++]빌드 프로세스  (0) 2021.03.09
[C++]메모리 구조  (0) 2021.03.09
[C++]연산자 오버로딩  (0) 2021.03.09
반응형

1. extern vs static

  1. 링크의 방향을 결정(외부 또는 외부)
  2. extern int a
    • 다른 파일의 전역 변수 a를 사용함
  3. extern void func()
    • 함수는 기본값이 extern(생략되어 있음)
  4. static int a
    • 다른 파일에서 a를 찾을 수 없음
  5. static void bar()
    • 파일 내부에서만 호출 가능한 함수

2. gcc debug

  1. 컴파일
gcc main.cpp -g
  1. gdb 실행
gdb main.out
  1. 디버깅 시작

    • start 입력
  2. 다음 줄 실행

    • next 입력
  3. 뷰어 제공

    • ctrl + x + a
    • n : 다음 줄 이동
    • break 26 : 26번줄 브레이크 적용
    • break 함수이름 : 함수 첫 호출에 브레이크 적용
    • continue : 브레이크 포인터에서 멈춤
    • step : 함수 안으로 들어감
    • print 변수명: 변수 정보 출력
    • bt : 콜 스택을 보여줌

3. static library

  1. 오브젝트 파일들을 모아 하나의 파일로 생성한 것
  2. 이름은 lib이름.a 형태
  3. 링킹 시점에 실행파일에 바인딩 된다.

4. Dynamic library

  1. 이름은 lib이름.so 형태
  2. 빌드시 -fPIC 옵션 줘야함
    • 여러 프로그램에서 콜 될 수 있도록 생성시 주소를 상대주소로 설정
  3. loadtime에 바인딩 하는 방법
  4. runtime에 바인딩 하는 방법

참고

코드없는 프로그래밍(유투브)

반응형

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

[C++]스마트 포인터  (0) 2021.03.09
[C++]LR value 및 최적화  (0) 2021.03.09
[C++]메모리 구조  (0) 2021.03.09
[C++]연산자 오버로딩  (0) 2021.03.09
[C++]기초 내용 정리  (0) 2021.03.09
반응형

1. 메모리 구조

2. 데이터 영역

  1. 전역, static 변수가 저장됨(rw 영역)
  2. 초기화 되지 않으면 bss영역에 저장
  3. 프로그램이 종료되면 반환

3. 스택 영역

  1. 일반적인 변수가 저장되며 함수 블록 단위로 저장
  2. 하나의 블록은 인자, 일반변수, 리턴값으로 저장
  3. 함수가 종료되면 LIFO로 함수 블록이 반환
  4. 런타임 시간에 크기 변경 불가

4. 힙 영역

  1. 동적 메모리 영역
  2. 할당 후 해제가 반드시 필요함
  3. 읽고 쓰는 속도가 스택에 비해 약간 느림

5. 메모리 관리 방법

  1. 일반 적인 경우 스마트 포인터를 사용

    • delete를 해주지 않아도 자동으로 메모리 해제됨
  2. 배열 형태 사용 필요시 vector를 사용

6. 메모리 누수 찾는 방법(팁)

  1. valgrind 프로그램명

7. 언제 스택? 힙?

  1. 데이터량이 mb 이하이면 스택(array 사용)
std::array<int, 1000> ar;
  1. 데이터량이 mb 이상이면 힙(vector 사용)
std::vector<cat, 1000000> ve;
  1. 왜?
    • 스택은 위에서부터 그냥 쌓기 때문에 힙보다 빠름

참고

코드없는 프로그래밍(유투브)

반응형

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

[C++]스마트 포인터  (0) 2021.03.09
[C++]LR value 및 최적화  (0) 2021.03.09
[C++]빌드 프로세스  (0) 2021.03.09
[C++]연산자 오버로딩  (0) 2021.03.09
[C++]기초 내용 정리  (0) 2021.03.09

+ Recent posts

반응형