Qt 라이브러리는 범용 템플릿 기반 컨테이너 클래스 세트를 제공합니다. 
해당 클래스는 지정된 유형의 항목을 저장할 경우 사용하는데, 예를 들어 가변적인 QString 배열이 필요한 경우 QVector을 이용합니다.

Qt 컨테이너는 STL 컨테이너보다 가볍고 안전하며 사용하기 쉽게 설계되었습니다. 
STL에 익숙하지 않거나 "Qt 방식"을 선호하는 경우 STL 컨테이너 대신 Qt 컨테이너를 사용할 수 있습니다.

 

Qt 컨테이너 및 STL 컨테이너 대응 관계

Qt 컨테이너 STL 컨테이너
순차 컨테이너
QVector std::vector
- std::deque
QList -
QLinkedList std::list
- std::forward_list
연관 컨테이너
QMap std::map
QMultiMap std::multimap
- std::set
- std::multiset
QHash std::unordered_map
QMultiHash std::unordered_multimap
QSet std::unordered_set
- std::unordered_multiset


Qt 컨테이너 클래스는 암시적으로 공유되고 재진입되며 속도, 낮은 메모리 소비 및 최소 인라인 코드 확장을 위해 최적화되어 실행 파일이 더 작아집니다. 또한, 액세스하는데 사용되는 모든 쓰레드에서 읽기 전용 컨테이너로 사용되는 상황에서는 쓰레드로부터 안전합니다.

Qt는 QList, QLinkedList, QVector, QStack 및 QQueue와 같은 순차적 컨테이너를 제공하는데, 대부분의 경우 QList 사용을 권고합니다.

QList는 배열 목록으로 구현되지만 prepend()와 append() 명령을 활용하여 좋은 성능을 보여줍니다.

연결리스트가 필요하다면 QLinkedList, 항목이 연속 메모리 위치를 차지하게 하려면 QVector, QStack 및 QQueue는 LIFO 및 FIFO 의미를 제공하는 클래스입니다.

Qt는 QMap, QMultiMap, QHash, QMultiHash 및 QSet과 같은 연관 컨테이너도 제공합니다. 

"Multi" 컨테이너는 단일 키와 관련된 여러 값을 편리하게 지원합니다. 

"Hash" 컨테이너는 정렬 된 세트에서 이진 검색 대신 해시 함수를 사용하여 더 빠른 조회를 제공합니다.
QCache 및 QContiguousCache 클래스는 제한된 캐시 스토리지에서 오브젝트의 효율적인 해시 조회를 제공합니다.

 

Qt 컨테이너 클래스

Class Summary
QList<T>

가장 일반적으로 사용되는 컨테이너 클래스이고 인덱스로 액세스 할 수있는 주어진 유형 (T)의 값 목록을 저장합니다. 

내부적으로 QList는 배열을 사용하여 구현되므로 인덱스 기반 액세스가 매우 빠릅니다.
QList::append() 및 QList::prepend()를 사용 시 목록의 끝에 항목을 추가, QList::insert()를 사용 시 중간에 항목을 삽입할 수 있습니다.

다른 컨테이너 클래스보다 QList는 실행 파일에서 가능한 적은 코드로 확장하도록 고도로 최적화 되었습니다.

QLinkedList<T>

QLinkedList 이것은 정수 인덱스 대신 반복자를 사용하여 항목에 액세스한다는 점을 제외하고 QList와 유사합니다. 

또한 목록이 많을 경우 중간에 삽입 시 QList보다 우수한 성능을 제공하며 반복자 의미가 더 좋습니다.
QLinkedList에서 항목을 가리키는 반복자는 항목이 존재하는 한 계속 유효하지만,

QList에 대한 반복자는 삽입 또는 제거 후에 유효하지 않을 수 있습니다.

QStringList<T> QList<T>를 상속받은 클래스입니다.
QVector<T>

메모리의 인접한 위치에 주어진 유형의 값 배열을 저장합니다. 

벡터의 앞이나 가운데에 삽입하면 메모리에서 한 위치 씩 많은 항목을 이동해야 할 수 있으므로 상당히 느릴 수 있습니다. 

연속 메모리를 이용해 구현되었으며 인덱스 기반의 랜덤 엑세스에 최적화 되어 있습니다. 

QStack<T>

"LIFO (Last In, First Out)" 시맨틱을 제공하는 QVector의 편리한 서브 클래스입니다. 

QVector에 이미 존재하는 함수에 push(), pop() 및 top() 함수를 추가하였습니다.

QQueue<T>

"FIFO" 의미를 제공하는 QList의 편리한 서브 클래스입니다.

QList에 이미있는 함수에 enqueue(), dequeue() 및 head() 함수를 추가하였습니다.

QSet<T> 빠른 검색이 가능한 single-valued mathematical set를 제공합니다.
QMap<Key,T>

Key 유형의 키를 T 유형의 값에 맵핑하는 사전 (associative array)을 제공합니다. 

일반적으로 각 키는 단일 값과 연관됩니다. 

QMap은 데이터를 키 순서로 저장하고 순서가 중요하지 않은 경우에는 QHash를 사용하는 것이 좋습니다.

QMultiMap<Key,T> 다중 값 맵, 즉 하나의 키가 여러 값과 연관 될 수있는 맵을 위한 인터페이스를 제공하는 QMap의 서브 클래스입니다.
QHash<Key,T>

QMap과 거의 동일한 API를 갖지만 더욱 빠른 조회를 제공합니다. 

QHash는 데이터를 임의의 순서로 저장합니다.

QMultiHash<Key,T> 다중 값 해시를 위한 인터페이스를 제공하는 QHash의 서브 클래스입니다.

 

컨테이너는 중첩될 수 있습니다. 

예를 들어, 키 유형이 QString이고 값 유형이 QList  인 QMap <QString, QList >를 사용하는 것이 가능합니다.
컨테이너는 컨테이너와 이름이 같은 개별 헤더 파일에 정의됩니다.

다양한 컨테이너에 저장된 값은 할당 가능한 데이터 유형일 수 있습니다.

자격을 얻으려면 형식은 기본 생성자, 복사 생성자 및 할당 연산자를 제공해야 합니다.

 

이는 int 및 double, pointer 유형, QString, QDate, QTime와 같은 Qt 데이터 유형 등 컨테이너에 저장하고자 하는 대부분의 데이터 유형을 포함하지만, QObject 또는 QObject 하위 클래스(QWidget, QDialog, QTime)는 포함되지 않습니다.

QList<QWidget>를 인스턴스화 하려고 하면 컴파일러는 QWidget의 복사 생성자와 할당 연산자가 비활성화되어 있다고 알려줄 것 입니다.

 

복잡도

알고리즘의 복잡도 컨테이너의 항목 수가 증가함에 따라 각 컨테이너 클래스의 속도에 관한 것입니다. 

예를 들어, QLinkedList의 중간에 항목을 삽입하는 것은 QLinkedList에 저장된 항목 수에 관계없이 빠르게 수행됩니다. 

반면, QVector 중간에 항목을 삽입할 경우 QVector에 많은 항목이 포함되어 있으면 항목의 절반이 메모리에서 한 위치로 이동해야 하므로 시간이 많이 걸립니다.

알고리즘 복잡도를 설명하기 위해 "big Oh" 표기법에 따라 아래의 용어를 사용합니다.

일정 시간: O(1). 컨테이너에 몇 개의 항목이 있는지에 관계없이 동일한 시간이 필요한 경우 함수는 일정한 시간에 실행된다고합니다.

   Ex) QLinkedList::insert()

 

로그 시간: O(log n). 로그 시간으로 실행되는 함수는 실행 시간이 컨테이너에있는 항목 수의 로그에 비례하는 함수입니다.

   Ex) qBinaryFind()

 

선형 시간: O(n). 선형 시간으로 실행되는 기능은 컨테이너에 저장된 항목 수에 정비례하는 시간으로 실행됩니다.

   Ex) QVector::insert()

 

선형 로그 시간: O(n log n). 선형 로그 시간으로 실행되는 함수는 선형 시간 함수보다 점진적으로 느리지 만 2 차 시간 함수보다 빠릅니다.

 

Qt 컨테이너 클래스별 복잡도