C ++에서 std :: vector vs std :: array


283

a std::vectorstd::arrayin C 의 차이점은 무엇입니까 ? 언제 다른 것을 선호해야합니까? 각각의 장단점은 무엇입니까? 나의 교과서가하는 것은 그것들이 어떻게 같은지를 열거하는 것입니다.


1
나는 비교를 찾고 있어요 std::vectorstd::array방법과 용어가 다릅니다.
Zud December

Zud std::array는 C ++ 배열과 다릅니다. std::array클래스의 사용자로부터 포인터를 숨기려는 주요 목적으로 C ++ 배열을 둘러싼 매우 얇은 래퍼입니다. 답변을 업데이트하겠습니다.
ClosureCowboy

설명을 반영하기 위해 질문 제목과 텍스트를 업데이트했습니다.
Matteo Italia

답변:


318

std::vector는 힙에 저장된 동적 배열 1 을 캡슐화하는 템플릿 클래스로 , 요소가 추가되거나 제거되면 자동으로 증가 및 축소됩니다. STL의 나머지 부분에서 잘 작동하도록하는 모든 후크 ( begin(),, end()반복자 등)를 제공합니다 . 또한 벡터 가운데에 요소를 삽입하는 것과 같이 일반 배열에서 번거로울 수있는 작업을 수행 할 수있는 몇 가지 유용한 방법이 있습니다 (다음 요소를 장면 뒤로 이동하는 모든 작업을 처리 함).

힙에 할당 된 메모리에 요소를 저장하기 때문에 정적 배열과 관련하여 약간의 오버 헤드가 있습니다.

std::array정적 크기의 배열을 캡슐화하는 템플릿 클래스는 객체 자체에 저장되므로 스택에서 클래스를 인스턴스화하면 배열 자체가 스택에있게됩니다. 크기는 컴파일 타임에 알고 있어야하며 (템플릿 매개 변수로 전달됨) 커지거나 줄어들 수 없습니다.

보다 제한적 std::vector이지만 실제로는 특히 작은 크기의 경우 더 효율적입니다. 실제로 C 스타일 배열을 중심으로 경량 래퍼이기 때문입니다. 그러나 포인터에 대한 암시 적 변환이 비활성화되어 있고 std::vector다른 컨테이너의 많은 STL 관련 기능을 제공 하므로 STL 알고리즘 및 공동으로 쉽게 사용할 수 있으므로 더 안전합니다. 어쨌든 고정 크기의 매우 제한적인 경우보다 크기가 훨씬 유연합니다 std::vector.

에 대한 소개를 보려면 이 기사를std::array 살펴보십시오 . 가능한 조작 에 대한 빠른 소개 와 조작에 대해서는 해당 문서를 참조하십시오 .std::vector


  1. 실제로, 나는 표준에서 서로 다른 연산의 최대 복잡성 (예 : 일정한 시간에 무작위 접근, 선형 시간에 모든 요소에 대한 반복, 일정한 상각 시간에 마지막에 요소 추가 및 제거, 등)이지만 AFAIK는 동적 배열을 사용하는 것 외에는 이러한 요구 사항을 충족시키는 다른 방법이 없습니다. @Lucretiel 의해 명시된 바와 같이, 표준은 실제로되도록 소자가 연속적으로 저장되는 것을 요구 그것이 동적 배열 여기서 연관된 할당 둔다를 저장.

6
각주에 대하여 : 참이긴하지만, 표준은 내부 요소에 대한 포인터 산술이 작동한다고 보증합니다. 이는 배열이어야한다는 것을 의미합니다. & vec [9]-& vec [3] == 6 참입니다.
Lucretiel

9
그 벡터는 자동으로 줄어들지 않지만 C ++ 11부터 shrink_to_fit을 호출 할 수 있습니다.
디노

정적 배열 이라는 용어에 완전히 혼란스럽고 올바른 용어가 무엇인지 잘 모르겠습니다. 정적 변수 배열이 아닌 정적 크기 배열을 의미합니다 (정적 스토리지를 사용하는 배열). stackoverflow.com/questions/2672085/... . 올바른 용어는 무엇입니까? 정적 배열은 고정 된 크기의 배열에 대해 조잡한 용어입니까?
Z boson

3
@Zboson : 그것은 단지 당신 만이 아니라 정적 은 상당히 남용 된 용어입니다. staticC ++ 의 very 키워드는 서로 관련이없는 세 가지 의미를 가지고 있으며,이 용어는 종종 컴파일 타임에 고정되는 내용에 대해 이야기하는 데 사용됩니다. "정적 크기"가 좀 더 명확하기를 바랍니다.
Matteo Italia

3
참고로 한 가지 : (당신이이 안되는 실시간 프로그래밍을위한 어떤 시작 후 동적 할당 / 해제는) 표준 : 배열이 아마 표준 : : 벡터보다 선호 될 것이다.
TED

17

std::vector<T>수업 사용하기 :

  • 입니다 ... 그냥 빨리 사용하는 등 만 내장 배열 일을하고있는 가정, 배열 내장 (읽기 및 기존 요소에 대한 쓰기) 당신이 할 수 있습니다.

  • ... 새 요소가 삽입되면 자동으로 크기가 조정됩니다.

  • ... 벡터 의 시작 또는 중간 에 새로운 요소를 삽입 하여 나머지 요소를 "위로" "이동"할 수 있습니다 (이치가 있습니까?). 또한 요소의 어느 곳에서나 요소를 제거 std::vector하고 나머지 요소를 자동으로 아래로 이동시킵니다.

  • ... at()방법 으로 범위 확인 읽기를 수행 할 수 있습니다 ( []이 확인을 수행하지 않으려면 항상 인덱서를 사용할 수 있습니다 ).

다음과 같은 가지 주요주의 사항이 있습니다 std::vector<T>.

  1. 기본 포인터에 대한 안정적인 액세스 권한이 없으므로 배열 주소를 요구하는 타사 함수를 처리하는 경우 문제 있습니다.

  2. std::vector<bool>클래스는 바보입니다. 배열이 아닌 압축 비트 필드로 구현됩니다. bools 배열을 원하면 피하십시오 !

  3. 사용하는 동안 std::vector<T>s는 같은 수의 요소를 가진 C ++ 배열보다 조금 더 커질 것입니다. 현재 크기와 같은 소량의 다른 정보를 추적해야하기 때문에 std::vector<T>크기를 조정할 때마다 필요한 공간을 더 많이 확보하기 때문입니다. 새 요소를 삽입 할 때마다 크기를 조정하지 않아도됩니다. 이 동작은 사용자 정의를 제공하여 변경할 수 allocator있지만 그렇게 할 필요는 없다고 생각했습니다!


편집 : 질문에 대한 Zud의 답변을 읽은 후에 이것을 추가해야한다고 생각했습니다.

std::array<T>클래스는 C ++ 배열과 동일하지 않다. std::array<T>C ++ 배열 주위의 매우 얇은 래퍼이며 클래스 사용자에게 포인터를 숨기려는 주요 목적으로 사용됩니다 (C ++에서는 배열이 암시 적으로 포인터로 캐스트되어 종종 끔찍한 영향을 미칩니다). std::array<T>클래스는 크기 (길이), 매우 유용 할 수 있습니다 저장합니다.


5
동적으로 할당 된 내장 어레이를 사용하는 것만 큼 '빠른'반면, 자동 어레이를 사용하면 성능이 상당히 다를 수 있습니다 (로컬 리티 효과 때문에 할당하는 동안뿐만 아니라)
Ben Voigt

4
C ++ 11에서 비 부울 벡터 이상의 경우, 당신은 호출 할 수 있습니다 data()A의 std::vector<T>기본 포인터를 얻을 수 있습니다. 요소 0의 주소를 사용할 수도 있습니다 (C ++ 11과 함께 작동하도록 보장하고 아마도 이전 버전에서도 작동 할 것입니다).
Matt

16

@MatteoItalia의 요점을 강조하기 위해 효율성 차이는 데이터가 저장되는 위치입니다. 힙 메모리 (로 필요 vector)는 메모리를 할당하기 위해 시스템을 호출해야하며주기를 계산하는 경우 비용이 많이들 수 있습니다. array메모리는 스택 포인터를 조정하여 할당되고 함수 시작시 한 번만 수행되기 때문에 스택 메모리 (에 대해 가능 )는 시간 측면에서 거의 "제로 오버 헤드"입니다. 스택은 또한 메모리 조각화를 피합니다. 확실히, std::array항상 스택에있는 것은 아닙니다. 할당하는 위치에 따라 다르지만 여전히 벡터에 비해 힙에서 적은 메모리 할당이 필요합니다. 당신이 있다면

  • 작은 "배열"(100 개 요소 이하)-(일반적인 스택은 약 8MB이므로 코드가 재귀 적이라면 스택에 몇 KB 이상을 할당하지 마십시오)
  • 크기가 고정됩니다
  • 수명이 함수 범위 내에 있거나 상위 클래스와 동일한 수명을 가진 멤버 값입니다.
  • 당신은 사이클을 세고 있습니다.

확실히 std::array벡터를 사용하십시오. 이러한 요구 사항 중 하나라도 해당되지 않으면를 사용하십시오 std::vector.


3
좋은 대답입니다. "확실히 std :: array가 항상 스택에있는 것은 아니며 할당 위치에 따라 다릅니다."어떻게 많은 요소가있는 스택에 std :: array를 만들 수 없습니까?
Trilarion

4
@Trilarion을 사용 new std::array하거나 ' new '를 사용하여 할당하는 클래스의 멤버로 만듭니다.
Mark Lakata

따라서 이것은 new std::array여전히 컴파일 타임에 크기를 알기를 기대하지만 크기를 변경할 수는 없지만 여전히 힙에 남아 있습니까?
Trilarion

예. new std::arrayvs 를 사용하면 큰 이점이 없습니다 new std::vector.
Mark Lakata

12

다차원 배열 사용을 고려하는 경우 std :: array와 std :: vector 사이에 하나의 추가 차이점이 있습니다. 다차원 std :: array는 ac 스타일 배열과 마찬가지로 모든 차원에서 메모리에 요소가 압축되어 있습니다. 다차원 std :: vector는 모든 차원에서 압축되지는 않습니다.

다음과 같은 선언이 주어집니다.

int cConc[3][5];
std::array<std::array<int, 5>, 3> aConc;
int **ptrConc;      // initialized to [3][5] via new and destructed via delete
std::vector<std::vector<int>> vConc;    // initialized to [3][5]

c 스타일 배열의 첫 번째 요소 (cConc) 또는 std :: array (aConc)의 첫 번째 요소에 대한 포인터는 각 선행 요소에 1을 추가하여 전체 배열을 반복 할 수 있습니다. 그들은 단단히 포장되어 있습니다.

벡터 배열 (vConc) 또는 포인터 배열 (ptrConc)의 첫 번째 요소에 대한 포인터는 첫 5 개의 요소 (이 경우)를 통해 반복 될 수 있으며 12 바이트 (내 시스템에는)의 오버 헤드가 있습니다. 다음 벡터.

이것은 [3] [1000] 배열로 초기화 된 std :: vector> 배열이 [1000] [3] 배열로 초기화 된 것보다 메모리에서 훨씬 작으며 둘 다 std보다 메모리에서 더 크다는 것을 의미합니다. 어느 쪽이든 할당 된 배열.

즉, 메모리 오버 헤드를 고려하지 않고 다차원 벡터 (또는 포인터) 배열을 openGL에 전달할 수는 없지만 다차원 std :: array를 openGL에 순진하게 전달하여 해결할 수 있습니다.


-17

벡터는 컨테이너 클래스이고 배열은 할당 된 메모리입니다.


23
귀하의 답변은 std::vector<T>vs 를 다루는 것 같지만 T[]질문은 std::vector<T>vs 에 관한 것 std::array<T>입니다.
Keith Pinson
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.