※ std::shared_ptr 요약
C++11에 새로 추가된 스마트 포인터인 shared_ptr에 대한 내용이다.

스마트 포인터란, 사용하지 않는 메모리나 사용이 끝난 메모리를 자동으로 해제/관리 해주는 것을 의미하는 것으로써 JavaC#의 가비지 컬렉터와 비교 했을때 성능의 손해는 거의 없으면서 메모리 관리의 이점을 얻을 수 있으므로 편하고도 안전하다.

스마트 포인터는 메모리 누수 관리에 자신이 없는 초보자들이나 복잡하고 거대한 프로젝트를 진행할때 사용하면 적당할 거 같다.

그렇지만 필자는 스마트 포인터를 거의 사용하지 않는다. 아직은 직접 할당, 해제를 해줘야 안심?이 되기 때문이다.


※ std::shared_ptr 특징
- 레퍼런스(참조) 카운팅을 지원한다.
- 명시적인 delete를 해주지 않아도 마지막에 참조하는 곳에서 스코프를 벋어날때 자동으로 해제된다.
- 특별히 어려운 문법을 배우지 않고도 메모리 관리에 큰 편의를 제공받는다.

※ std::shared_ptr을 사용해야 하는 경우

- 메모리 관리에 자신없는 분들이 메모리를 관리해야 할 때

- 거대하고 복잡한 프로젝트를 진행 할 때

- C++11이나 그 이상을 지원하는 컴파일러를 사용 할 때


 

※ std::array 요약
std::array는 C++11에 새롭게 추가된 컨테이너 라이브러리로써, 크기가 고정되어 있다는 것을 제외하면 std::vector와 비슷하다.
크기가 고정이므로 스택에 저장되며 C++03까지는 없었던 고정 길이 배열 자료구조 컨테이너로써 기존의 배열을 대체하기에 완벽하다.

※ std::array 특징
- 배열을 대체할 수 있다.
- 정적 배열이므로 스택에 저장된다. (std::vector는 힙 메모리에 저장된다!)
- 데이터가 연속된 위치에 저장되므로 랜덤 액세스가 가능하고 접근 속도도 빠르다.
- 정적이므로 push_back(), pop_back(), insert(), erase(), clear(), resize(), reserve(), capacity()멤버 함수는 지원하지 않는다.

※ std::array를 사용해야 하는 경우
- C++11이 지원되는 컴파일러라면 배열 대신 사용하면 좋다.
(필자는 C++11이 지원되는 컴파일러에서 작업하면 배열 대신 무조건 std::array를 사용한다. STL과 새롭게 추가되는 문법 등과의 결합도가 좋고 속도도 빠르며, 무엇보다 (조금이지만)편하기 때문이다.)


 

※ std::deque 요약
std::deque는 Double Ended Queue의 약자로써, 시퀀스 컨테이너다.

필자는 시뮬레이터 서버를 제작할 때와 Singleton 방식의 Log Class를 제작할때 std::deque의 사용을 고려해본 적이 있다.


※ std::deque 특징

- 크기가 가변적이다. (사실 std::array를 제외한 거의 모든 STL 컨테이너의 특징이다.)

- 앞(front)과 뒤(back)에서의 삽입, 삭제 성능은 좋지만 중간에서의 삽입, 삭제는 그다지 좋지 않다.

- std::deque는 Stack과 Queue가 결합된 자료구조로써 연결 리스트보다 구현하기가 어렵다.

- std::vector처럼 랜덤 액세스가 가능하다.


※ std::deque와 std::vector
- std::deque와 std::vector의 멤버 함수 기능이나 사용 방법은 거의 동일하다.

- std::vector는 뒤(back)에서의 삽입, 삭제 성능이 좋지만 std::deque는 앞(front), 뒤(back), 모두에서 좋다.

- std::deque의 앞, 뒤 삽입, 삭제 성능을 제외한 다른 위치에서의 삽입, 삭제는 std::vector가 더 좋다.

- 둘 다 랜덤 액세스가 가능하다.

 

※ std::deque를 사용해야 하는 경우

- 앞과 뒤에서 삽입, 삭제를 자주 할 때

- 저장할 데이터의 개수가 가변적 일 때

- 데이터 검색을 거의 하지 않거나, 아예 안 할 때 (검색을 해야 한다면 std::map이나 std::set 등의 연관 컨테이너 사용을 고려)

- 랜덤 액세스를 해야 할때

- 서버처럼 받은 패킷을 차례대로 처리할 때 (이 때는 범용적인 deque보다 좀 더 좋은 성능의 독자적인 자료구조를 만들기도 함)


 

 

 

※ STD::forward_list 요약
std::list가 양방향(double linked list)이라면 std::forward_list는 단방향(single linked list)이다.
단방향 연결 리스트라 양방향인 std::list보다 메모리 사용량이나 처리 속도면에서 조금 유리하다.
double linked list가 필요하다면 std::list를, single linked list로도 충분하다면 std::forward_list를 사용한다.

※ std::forward_list 특징
- single linked list(단일 연결 리스트) 자료구조를 이용하여 만든 시퀀스 컨테이너다.
- 설계 디자인을 std::list에 맞춘다.(STL은 범용성을 지향하므로 다른 컨테이너들도 마찬가지다.)
- 속도와 사이즈, 즉 성능을 최우선으로 설계, 제작되었다.
- 다른 STL 컨테이너에 있는 size 함수를 제공하지 않는다.
- size는 다음과 같이 구한다. -> size_t size = std::distance( list.begin(), list.end() )

※ std::forward_list와 std::list
- std::list는 양방향으로 이동 가능하지만 std::forward_list는 한 방향으로만 이동할 수 있다.
- std::list보다 삽입/삭제 속도가 아주 약간 더 빠르다.
- 양방향인 std::list에 비해 메모리를 적게 사용한다. 각 요소 뿐만이 아닌, 컨테이너 자체 사이즈도 더 작다.
- 삽입과 삭제는 지정한 요소의 다음 요소에 한해서만 가능하다.(단방향이므로 당연하다)
- 구현의 복잡성과 성능 문제 때문에 std::list에서 제공하는 insert와 erase를 제공하지 않는다.

 

※ std::forward_list를 사용해야 하는 경우

- double linked list가 아닌 single linked list로도 충분할때


 

 

※ std::set 요약
std::set은 std::map과 상당히 비슷한 연관 컨테이너이다. 다른 점이 있다면 value 없이 key만으로 이뤄졌다는 것 정도이다.
std::set은 노드 기반 컨테이너이며 균형 이진 트리로 구현 되므로 균형 이진 트리의 모든 특징을 갖는다.
std::set은 std::map과 마찬가지로 중복된 key를 저장할 수 없으므로, 중복 저장하고 싶다면 std::multiset을 사용해야 한다.
동일 타입 집합이라는 점에서는 std::vector와 같지만 요소가 정렬된 위치에 삽입 된다는 점이 다르다.

※ std::set 특징
- std::set은 std::map과 상당히 비슷하다. 차이점이라면 std::map과 다르게 value 없이 key만 저장한다는 것 정도다.
- std::set의 key는 중복될 수 없다. 중복 저장해야 한다면 std::multiset을 사용한다.
- 데이터 삽입과 동시에 정렬이 일어난다.
- 정렬은 key를 기준으로 정렬되며 기본 정렬 기준은 less(오름차순) 정렬이다.
- 검색 또한 key를 기준으로 검색(이분검색)한다.
- 검색시 균형 이진 트리를 이용한 로그 시간 검색 복잡도를 보장한다.

※ std::set을 사용해야 하는 경우
- 삽입과 동시에 정렬해야 할때
- key가 있는지 없는지 알아야 할때
- 많은 데이터를 보관해야 하고, 동시에 검색이 빨라야 할때
- 많은 데이터가 중복 되어서는 안 되며 빠른 검색으로 존재 여부를 신속하게 알고 싶을때!

 

※ std::map 요약
필자가 std::vector와 함께 많이 사용하는 연관 컨테이너 std::map에 대한 설명이다.
std::map은 key와 value의 쌍을 원소로 저장(pair 객체로 저장)하며, set처럼 원소의 key는 중복될 수 없다.
중복 key를 저장해야 한다면 std::multimap을 사용하여야 한다.
연관 컨테이너는 어떠한 key와 짝을 이루어 자료를 보관하는데, 자료를 넣거나 빼거나 찾을 때는 key를 이용하여야 한다.

※ std::map 특징
- std::map은 레드-블랙 트리(Red-Black Tree) 자료구조이다.
- std::map의 key는 중복될 수 없다. 중복 저장해야 한다면 std::multimap을 사용한다.
- 데이터 삽입과 동시에 정렬이 일어난다.
- 정렬은 key를 기준으로 정렬되며 기본 정렬 기준은 less(오름차순) 정렬이다.
- 검색 또한 key를 기준으로 검색(이분검색)한다.
- std::map의 원소는 std::pair 객체로 저장된다.
- 저장할 자료가 적을때는 메모리 낭비와 검색시 오버헤드가 생겨 대포로 파리 잡는 격이다.

※ std::map을 사용해야 하는 경우
- 삽입과 동시에 정렬해야 할때
- 많은 데이터를 보관해야 하고, 동시에 검색이 빨라야 할때
- 데이터 삽입, 삭제가 적을때


 

※ std::list 요약
std::list는 double linked list(이중 연결 리스트)라는 자료구조를 이용하여 만든 시퀀스 컨테이너다.
템플릿 기반이므로 임의 타입을 요소로 가질 수 있으며, 요소 개수에 따라 동적으로 메모리를 관리한다.
double linked list로 되어 있기에 double linked list의 특징을 거의 그대로 가지고 있으며 linked list 자료구조에 대한 이해가 있어야 알맞는 상황에 알맞게 사용할 수 있다. 필자는 std::list를 거의 사용하지 않는다. 나뻐서 안 사용한다기 보다는 std::vector로도 충분한 상황이 대부분이기 때문이다.

※ std::list 특징

- 고정 길이인 배열에 비해 길이가 가변적이다.
- std::vector와 달리 데이터의 중간 삽입, 중간 삭제 속도가 빠르다.
- 데이터 중간 삽입, 삭제시 요소 개수에 상관없이 동일한 상수시간이 소요된다.(상수 시간 복잡도의 수행 성능 보장)

- list의 순회 속도는 O(n), 즉 요소 개수가 많을 수록 순회 속도는 느리다.

- 각 노드는 앞쪽, 뒤쪽 노드와 연결된 이중 연결 리스트다.(반대는 std::forward_list로써, 단일 연결 리스트다)

- 노드 기반이므로 []나 at()을 지원하지 않는다.

 

※ std::list를 사용해야 하는 경우

- 저장할 데이터의 개수가 가변적일때
- 저장된 요소를 자주 검색하지 않을때
- 중간에 데이터 삽입, 삭제가 자주 발생할때
- 랜덤 엑세스를 자주 안할때

 

'STL - Containers > list' 카테고리의 다른 글

[C++ STL] std::list 주요 멤버 함수 목록  (0) 2015.11.25

※ std::vector 요약
필자가 std::map과 함께 가장 많이 사용하는 시퀀스 컨테이너 std::vector에 대한 설명이다.
std::vector는 동일 타입의 자료 집합으로써 흔히 배열에 비유를 많이 한다.
또한 템플릿 기반이므로 임의 타입을 요소로 가질 수 있으며, 요소 개수에 따라 동적으로 메모리를 관리한다.
다른 컨테이너들에 비해 구조가 단순하고 사용 방법이 쉬우며 속도도 빠른편이다, 또 실용적이라 활용 빈도가 높다.

※ std::vector의 특징
- 배열을 대체할 수 있다.
- 동일 타입의 자료 집합이며 각 요소는 연속된 위치에 배치된다.
- 연속된 위치에 배치되므로 임의 위치를 빠른 속도로 액세스 할 수 있다.
- 최상위 레벨의 임의 접근 반복자를 제공하므로 STL의 거의 모든 알고리즘 사용 가능하다.
- 삽입, 삭제 속도가 느리다. 중간 삽입, 삭제는 더 느리다.

※ std::vector와 배열
- 배열의 크기는 고정이지만 std::vector는 요소 개수에 따라 자동(동적)으로 늘어난다.
- 배열과 std::vector 모두 사용 방법이 쉽다.
- 배열과 std::vector 모두 데이터를 연속된 위치에 순차적으로 저장한다.
- 연속된 위치에 순차적으로 저장하므로 랜덤 엑세스가 가능하다.
- 속도는 보통 배열이 std::vector보다 빠르다.
 
※ std::vector를 사용해야 하는 경우

- 저장할 데이터의 개수가 가변적일때
- 중간에 데이터 삽입, 삭제가 적거나 없을때
- 저장된 요소를 자주 검색하지 않을때
- 랜덤 엑세스를 자주 할때


 

 

※ std::tuple 요약
TR1부터 새롭게 추가된 std::tuple은 C++98에서 기본 제공하던 std::pair의 확장 버전으로써,
컴파일 시간에 명시되거나 추론될 수 있는 데이터형 요소들을 가지는 이종 목록(heterogeneous list)이다.
TR1인 Visual Studio 2010에서는 10개의 요소를 저장할 수 있고 
C++11을 부분 지원하는 Visual Studio 2013부터는 저장 가능한 항목 개수에 제한이 없고 
각각의 항목마다 개별 타입으로 지정 가능하다.

※ std::tuple 특징
std::tuple은 주로, 함수에서 2개 이상의 값을 반환해야할 때 사용한다.
기존에는 구조체를 이용하여 2개 이상의 값을 리턴했지만, 단순히 2개 이상의 값을 반환하기 위해
구조체를 만드는 것은 귀찮을 때도 있고 배보다 배꼽이 더 커지는 일이다.

필요한 헤더 파일
#include <tuple>

※예제
#include <iostream>
#include <string>
#include <tuple>

using namespace std;

enum { GET_STATE=0, GET_DESCRIPTION };

std::tuple<bool, string> CheckPowerOfTwo( const int nNum );

int main( )
{
     std::tuple<bool, string> tupleTest = CheckPowerOfTwo( 8 );
    
     //결과에 따른 문구 출력
     cout<<std::get<GET_DESCRIPTION>(tupleTest)<<endl;
    
     if( std::get<GET_STATE>(tupleTest) == true )
     {
          //2의 n승이 맞다면 추가 작업
     }
     else
     {
          //2의 n승이 아니라면 작업하지 않음
     }

     return 0;
}

std::tuple<bool, string> CheckPowerOfTwo( const int nNum )
{
    int nResult = nNum & (nNum-1);

    if( nResult == 0 )
    {
        return std::make_tuple( true, "2의 n승이 맞음" );
    }
    else
    {
        return std::make_tuple( false, "2의 n승이 아님" );
    }
}


※결과

마땅히 할 예제가 없어서 아무거나 한거니.. 대충 이런식으로 쓰는 것만 보면 되고,

문법은 다음 게시물부터 다루도록 하겠음.




+ Recent posts