C ++에서 배열 또는 std :: vectors를 사용하면 성능 격차는 무엇입니까?


208

C ++ 과정에서는 더 이상 새로운 프로젝트에서 C ++ 배열을 사용하지 않는 것이 좋습니다. 내가 아는 한 Stroustroup 자신은 배열을 사용하지 말 것을 제안합니다. 그러나 중요한 성능 차이가 있습니까?


2
성능 차이가 있다고 생각하는 이유는 무엇입니까?
Martin York

99
일반적으로 더 나은 기능을 사용하면 성능이 저하되기 때문입니다.
tunnuz

19
나는 조기 최적화에 동의하지만 더 나은 저장 방법을 미리 선택하는 것이 좋습니다. 실제 환경에서는 종종 코드를 출하하고 다음 제품을 개발하고 최적화 단계를 수행하지 않아도됩니다.
Ant

132
사람들이 "조기 최적화"를 외치지 않기를 바랍니다. 누군가 성능과 관련된 간단한 질문을 할 때마다! 질문에 대답하고 사람들이 조기에 무언가를하고 있다고 가정하지 마십시오.
d7samurai

4
@ d7samaurai : 아직 아무도 사용하지 않는 것을 보았습니다int main(int argc, const std::vector<string>& argv)
Mark K Cowan

답변:


189

C ++ 배열과 함께 new(즉, 동적 배열을 사용하여) 사용하지 않아야합니다. 크기를 추적해야하는 문제가 있으며 수동으로 삭제하고 모든 종류의 정리 작업을 수행해야합니다.

범위 검사가 없기 때문에 스택에서 배열을 사용하지 않는 것이 좋습니다. 배열을 전달하면 크기에 대한 정보가 사라집니다 (포인터에서 배열로 변환). 당신은 사용해야 boost::array작은 클래스의 C ++ 배열을 래핑하고 제공하는 경우에 size그것을 반복하는 기능과 반복자를.

이제 std :: vector 대 네이티브 C ++ 배열 (인터넷에서 가져옴) :

// Comparison of assembly code generated for basic indexing, dereferencing, 
// and increment operations on vectors and arrays/pointers.

// Assembly code was generated by gcc 4.1.0 invoked with  g++ -O3 -S  on a 
// x86_64-suse-linux machine.

#include <vector>

struct S
{
  int padding;

  std::vector<int> v;
  int * p;
  std::vector<int>::iterator i;
};

int pointer_index (S & s) { return s.p[3]; }
  // movq    32(%rdi), %rax
  // movl    12(%rax), %eax
  // ret

int vector_index (S & s) { return s.v[3]; }
  // movq    8(%rdi), %rax
  // movl    12(%rax), %eax
  // ret

// Conclusion: Indexing a vector is the same damn thing as indexing a pointer.

int pointer_deref (S & s) { return *s.p; }
  // movq    32(%rdi), %rax
  // movl    (%rax), %eax
  // ret

int iterator_deref (S & s) { return *s.i; }
  // movq    40(%rdi), %rax
  // movl    (%rax), %eax
  // ret

// Conclusion: Dereferencing a vector iterator is the same damn thing 
// as dereferencing a pointer.

void pointer_increment (S & s) { ++s.p; }
  // addq    $4, 32(%rdi)
  // ret

void iterator_increment (S & s) { ++s.i; }
  // addq    $4, 40(%rdi)
  // ret

// Conclusion: Incrementing a vector iterator is the same damn thing as 
// incrementing a pointer.

참고 : 당신과 함께 배열을 할당 할 경우 new비 클래스 객체 (일반 같은 할당 int사용자 정의 생성자없이) 또는 수업을 하고 당신은 당신의 요소를 사용하여, 처음 초기화하고 싶지 않아요 new때문에 성능 이점을 가질 수 -allocated 배열을 std::vector초기화하고 모든 요소를 시공시 기본값 (예를 들어 int의 경우 0) (나를 상기시키기 위해 @bernie에 크레딧).


77
망할 AT & T 구문을 누가 발명 했습니까? 내가 아는 경우에만 ... :)
Mehrdad Afshari

4
Visual C ++ 컴파일러에는 해당되지 않습니다. 그러나 GCC에게는 그렇습니다.
toto

5
내 대답의 요점은 벡터가 해당 포인터 작업보다 느릴 필요 가 없다는 입니다. 물론, 그것은 (쉽게도 디버그 모드를 사용 가능하게함으로써 달성하기 위해) : 수
요하네스 SCHAUB - litb

18
+1 "벡터 색인은 포인터를 인덱싱과 같은 망할 것입니다." 다른 결론도 마찬가지입니다.
Nawaz

3
@ Piotr99 나는 당신과 논쟁하지 않을 것이지만, 고급 언어 를 배우고 나서 어셈블리 배우면 인텔 구문은 일부 이전 버전, 접두사 (숫자), 접미사 (명령) 및 모호한 (메모리 액세스)보다 훨씬 더 의미가 있습니다. ) AT & T 구문의 특성.
Cole Johnson

73

마이크로 옵티 마이저를위한 프리앰블

생각해 내다:

"프로그래머는 프로그램의 중요하지 않은 부분의 속도에 대해 생각하거나 걱정하는 데 많은 시간을 낭비하며, 이러한 효율성에 대한 시도는 실제로 디버깅 및 유지 관리를 고려할 때 강력한 부정적인 영향을 미칩니다. 97 %의 시간 : 조기 최적화는 모든 악의 근원입니다. 그러나 우리는 그 중요한 3 %의 기회를 포기해서는 안됩니다. "

( 전체 견적 을 위해 변태 에 감사드립니다 )

벡터 (또는 다른 것) 대신 C 배열을 사용하지 마십시오. 단순하다고 생각하기 때문에 더 빠르다고 생각하기 때문입니다. 당신은 틀렸을 것입니다.

기본 벡터 (또는 필요에 맞게 안전한 컨테이너)를 사용하고 프로파일 러에 문제가 있다고 판단되면 더 나은 알고리즘을 사용하거나 컨테이너를 변경하여 최적화 할 수 있는지 확인하십시오.

이것은 우리가 원래의 질문으로 되돌아 갈 수 있다고 말했습니다.

정적 / 동적 배열?

C ++ 배열 클래스는 저수준 C 배열보다 더 잘 동작합니다. 왜냐하면 자신에 대해 많이 알고 C 배열이 할 수없는 질문에 대답 할 수 있기 때문입니다. 그들은 스스로를 청소할 수 있습니다. 더 중요한 것은 일반적으로 템플릿 및 / 또는 인라이닝을 사용하여 작성되는데, 이는 디버그에서 많은 코드에 나타나는 것이 릴리스 빌드에서 생성 된 코드를 거의 또는 전혀 해결하지 않음을 의미합니다.

대체로 두 가지 범주에 속합니다.

동적 배열

malloc-ed / new-ed 배열에 대한 포인터를 사용하면 std :: vector 버전만큼 빠르며 훨씬 안전하지 않습니다 ( litb의 게시물 참조 ).

따라서 std :: vector를 사용하십시오.

정적 배열

정적 배열을 사용하는 것이 가장 좋습니다.

  • std :: array 버전 만큼 빠름
  • 훨씬 덜 안전합니다

따라서 std :: array를 사용하십시오 .

초기화되지 않은 메모리

때로는 vector원시 버퍼 대신에 버퍼를 사용 vector하면 생성시 버퍼를 초기화 하기 때문에 눈에 띄는 비용이 발생 하지만 대체 코드는 베르니대답 한 것처럼 .

이 경우 또는 unique_ptr대신 코드 라인에서 vector예외가 아닌 경우 를 사용하여 처리 할 수 ​​있습니다 . 실제로 buffer_owner해당 메모리를 소유 할 클래스 를 작성하고 다음을 포함하여 쉽고 안전하게 액세스 할 수 있습니다. 크기 조정 ( realloc? 사용 ) 또는 필요한 항목 과 같은 보너스 .


1
정적 배열도 처리해 주셔서 감사합니다. 성능상의 이유로 메모리를 동적으로 할당 할 수없는 경우 std :: vector는 쓸모가 없습니다.
Tom

10
"정적 배열을 사용하는 것이 boost :: array 버전만큼 빠르다"고 말하면 얼마나 편향되어 있는지 보여줍니다. Boost : array는 정적 배열처럼 빠를 수 있습니다.
toto

3
@toto : 오해 : "정적 배열을 사용하는 것이 가장 좋습니다 (부스트 :: 배열 버전만큼 빠름) && (훨씬 덜 안전합니다)". 이를 명확하게하기 위해 게시물을 편집하겠습니다. 그건 그렇고, 의심의 이익에 감사드립니다.
paercebal

1
std :: array는 어떻습니까?
paulm

4
항상 전체 인용문을 표시하십시오. "프로그래머는 프로그램의 중요하지 않은 부분의 속도에 대해 생각하거나 걱정하는 데 많은 시간을 낭비하며, 이러한 효율성에 대한 시도는 실제로 디버깅 및 유지 관리를 고려할 때 강력한 부정적인 영향을 미칩니다. 97 %의 시간 : 조기 최적화는 모든 악의 근원입니다. 그러나 우리는 그 중요한 3 %의 기회를 포기해서는 안됩니다. " 그렇지 않으면 무의미한 소리가됩니다.
변태

32

벡터는 후드 아래의 배열입니다. 성능은 같습니다.

성능 문제가 발생할 수있는 한 곳은 벡터의 크기를 올바르게 시작하지 않는 것입니다.

벡터가 채워지면 자체 크기가 조정되므로 새로운 배열 할당, n 개의 복사 생성자, 약 n 개의 소멸자 호출, 배열 삭제가 이어질 수 있습니다.

생성 / 파괴가 비싸면 벡터를 올바른 크기로 만드는 것이 훨씬 좋습니다.

이것을 보여주는 간단한 방법이 있습니다. 생성 / 파기 / 복사 / 할당 될 때 표시되는 간단한 클래스를 만듭니다. 이러한 것들의 벡터를 만들고 벡터의 뒤쪽 끝에 밀어 넣으십시오. 벡터가 채워지면 벡터 크기가 조정될 때 일련의 활동이 발생합니다. 그런 다음 예상 크기의 요소 크기로 벡터를 사용하여 다시 시도하십시오. 차이점을 볼 수 있습니다.


4
펜던트 : 성능은 동일합니다. std :: vector는 약간의 부기 작업을 수행하므로 시간이 약간 걸립니다. OTOH, 자신의 동적 배열을 롤링 할 때 동일한 부기를 유지하게됩니다.
dmckee --- 전 운영자 고양이

네 이해했습니다. 그의 질문의 추진력은 무엇입니까? 성능 차이는 무엇입니까 ..... 나는 그것을 해결하려고했습니다.
EvilTeach

push_back을 호출하면 Gcc의 std :: vector는 실제로 용량을 하나씩 증가시킵니다.
bjhend

3
@bjhend 그렇다면 gcc의 std::vector소리는 표준과 호환되지 않습니까? 나는 표준이 vector::push_back일정한 복잡성을 상각 해야한다고 요구하며 , 각각의 용량을 1 씩 증가시키는 push_back것은 재 할당을 고려한 후 n ^ 2 복잡성이 될 것이라고 믿습니다. - 지수 용량의 증가 어떤 종류의 추정 push_backinsert, 데 실패 reserve벡터 내용을 복사에서 최대 일정한 요인 증가로 이어질 것이다. 1.5 지수 벡터 성장 인자는 실패한 경우 ~ 3 배 많은 사본을 의미합니다 reserve().
Yakk-Adam Nevraumont

3
@bjhend 당신이 틀렸다. 이 표준은 기하 급수적 성장을 금지합니다. § 23.2.3 단락 16은 "표 101은 일부 유형 컨테이너에 대해서는 제공되지만 다른 컨테이너에는 제공되지 않는 작업을 나열합니다. 구현은"컨테이너 "열에 표시된 모든 컨테이너 유형에 대해 이러한 작업을 제공해야합니다. 상각 된 일정한 시간이 걸리도록 구현해야한다. " (테이블 101은 push_back이있는 테이블입니다). 이제 FUD 확산을 중단하십시오. 어떠한 주류 구현도이 요구 사항을 위반하지 않습니다. Microsoft의 표준 C ++ 라이브러리는 1.5 배 증가하고 GCC는 2 배 증가합니다.
R. Martinho Fernandes

27

Mehrdad가 말한 것에 응답하기 위해 :

그러나 여전히 배열이 필요한 경우가 있습니다. 배열이 필요한 저수준 코드 (예 : 어셈블리) 또는 오래된 라이브러리와 인터페이스 할 때는 벡터를 사용하지 못할 수 있습니다.

전혀 사실이 아닙니다. 다음을 사용하면 벡터가 배열 / 포인터에서 잘 저하됩니다.

vector<double> vector;
vector.push_back(42);

double *array = &(*vector.begin());

// pass the array to whatever low-level code you have

이것은 모든 주요 STL 구현에 적용됩니다. 다음 표준에서는 (현재는 잘 작동하더라도) 작동해야합니다.


1
현재 표준은 그런 말을하지 않습니다. 암시 적이며 연속 저장소로 구현됩니다. 그러나 표준은 단순히 반복 액세스를 사용하는 임의 액세스 컨테이너라고 말합니다. 다음 표준은 명시 적입니다.
Frank Krueger

1
& * v.begin ()은 반복자를 역 참조한 결과에 & 연산자를 적용하기 만합니다. 역 참조는 모든 유형을 반환 할 수 있습니다. 주소 연산자를 사용하면 모든 유형을 다시 반환 할 수 있습니다. 표준에서는이를 연속 메모리 영역에 대한 포인터로 정의하지 않습니다.
Frank Krueger

15
표준의 1998 년 원본 텍스트는 실제로 그것을 요구하지는 않았지만, 2003 년에이 문제를 다루는 부록이 있었으므로 실제로 표준에 의해 다루어집니다. herbsutter.wordpress.com/2008/04/07/…
Nemanja Trifunovic

2
C ++ 03은 명시 적으로 &v[n] == &v[0] + n유효한 n경우 크기 범위 내에 있다고 말합니다 . 이 문장을 포함하는 단락은 C ++ 11에서는 바뀌지 않았습니다.
bjhend

2
왜 std :: vector :: data ()를 사용하지 않습니까?
paulm

15

C ++ 11에서 일반 배열을 사용해야하는 이유는 훨씬 적습니다.

특성에 따라 가장 빠른 것에서 가장 느린 것까지 세 가지 종류의 배열이 있습니다 (물론 구현 품질은 목록 3의 경우에도 실제로 빠를 수 있습니다).

  1. 컴파일 타임에 알려진 크기의 정적입니다. ---std::array<T, N>
  2. 런타임시 알려진 크기로 동적으로 크기가 조정되지 않습니다. 여기서 일반적인 최적화는 배열을 스택에 직접 할당 할 수 있다는 것입니다. -자료 없음 . 아마 dynarrayC ++ TS에서 C ++ 14 후. C에는 VLA가 있습니다
  3. 런타임시 동적 및 크기 조정 가능. ---std::vector<T>

의 경우 1. 고정 된 요소의 수, 사용과 일반 정적 배열 std::array<T, N>C ++ 십일인치

에 대한 2. 고정 된 크기의 실행시 지정된 배열,하지만 자신의 크기를 변경하지 않습니다, C에서 논의가 ++ 14 있지만 기술적 사양에 이동 된 마지막 14 ++ C 밖으로했다.

들어 3. std::vector<T> 일반적으로 힙 메모리를 요구합니다 . std::vector<T, MyAlloc<T>>사용자 지정 할당기로 상황을 개선하는 데 사용할 수 있지만 성능에 영향을 줄 수 있습니다 . 에 비해 장점T mytype[] = new MyType[n]; 은 크기를 조정할 수 있고 일반 배열처럼 포인터로 붕괴되지 않는다는 것입니다.

언급 된 표준 라이브러리 유형을 사용하여 배열이 포인터로 붕괴 되지 않도록하십시오 . 당신은 디버깅 시간을 절약하고 성능은 정확히 당신이 동일한 기능 세트를 사용하는 경우 일반 배열과 동일합니다.


2
std :: dynarray. n3690에 대한 국가 기관 의견을 검토 한 후이 라이브러리 구성 요소는 C ++ 14 작업 논문에서 별도의 기술 사양으로 선정되었습니다. 이 컨테이너는 n3797 기준으로 C ++ 14 초안의 일부가 아닙니다. 에서 en.cppreference.com/w/cpp/container/dynarray
모하메드 엘 - Nakib

1
아주 좋은 답변입니다. 간단하고 요약하면서도 더 많은 세부 사항.
Mohamed El-Nakib

6

STL로 이동하십시오. 성능 저하가 없습니다. 알고리즘은 매우 효율적이며 대부분의 사람들이 생각하지 않는 세부 정보를 처리하는 데 효과적입니다.


5

STL은 매우 최적화 된 라이브러리입니다. 실제로 고성능이 필요한 게임에서 STL을 사용하는 것이 좋습니다. 어레이는 일상적인 작업에 사용하기에 너무 오류가 발생하기 쉽습니다. 오늘날의 컴파일러는 매우 영리하며 실제로 STL을 사용하여 우수한 코드를 생성 할 수 있습니다. 수행중인 작업을 알고있는 경우 STL은 일반적으로 필요한 성능을 제공 할 수 있습니다. 예를 들어 필요한 크기로 벡터를 초기화하면 (시작부터 알고있는 경우) 기본적으로 배열 성능을 얻을 수 있습니다. 그러나 여전히 배열이 필요한 경우가 있습니다. 배열이 필요한 저수준 코드 (예 : 어셈블리) 또는 오래된 라이브러리와 인터페이스 할 때는 벡터를 사용하지 못할 수 있습니다.


4
벡터가 연속적이라면 배열이 필요한 라이브러리와 인터페이스하기가 여전히 쉽습니다.
Greg Rogers

예, 그러나 벡터의 내부 요소를 망가 뜨리려면 벡터를 사용할 때 이점이 적습니다. 그건 그렇고, 키워드는 "그렇지 않을 수 있습니다".
Mehrdad Afshari

3
벡터를 사용할 수없는 곳을 아는 경우는 하나뿐입니다. 크기가 0이면 & a [0] 또는 & * a.begin ()이 작동하지 않습니다. C ++ 1X 내부 버퍼가있는 요소를 유지 반환 a.data () 함수를 도입하여 그 문제를 해결한다
요하네스 SCHAUB - litb

필자가 작성한 특정 시나리오는 스택 기반 배열이었습니다.
Mehrdad Afshari

1
vec.data()데이터 및 vec.size()크기에 대한 C :와 벡터 또는 인접한 컨테이너와의 인터페이스 그렇게 쉽습니다.
Germán Diago

5

duli의 공헌에 대하여 .

결론은 정수 배열이 정수 벡터보다 빠릅니다 (이 예제에서는 5 배). 그러나 배열과 벡터는 더 복잡하거나 정렬되지 않은 데이터에 대해 동일한 속도로 회전합니다.


3

소프트웨어를 디버그 모드로 컴파일하면 많은 컴파일러가 벡터의 접근 자 함수를 인라인하지 않습니다. 이것은 성능이 문제가되는 상황에서 stl 벡터 구현을 훨씬 느리게 만듭니다. 또한 디버거에서 할당 된 메모리 양을 확인할 수 있으므로 코드를 쉽게 디버깅 할 수 있습니다.

최적화 된 모드에서 stl 벡터가 배열의 효율성에 접근 할 것으로 기대합니다. 많은 벡터 메소드가 이제 인라인되기 때문입니다.


언급하는 것이 중요합니다. 디버그 STL 항목 프로파일 링은 매우 느립니다. 그리고 사람들이 STL이 느린 이유 중 하나입니다.
Erik Aronesty

3

초기화되지 않은 버퍼 std::vector를 원할 때 (예 :의 대상으로 사용) 원시 배열과 원시 배열 을 사용하면 성능에 영향을 미칩니다 . 안memcpy()std::vector 기본 생성자를 사용하여 모든 요소를 초기화합니다. 원시 배열은 그렇지 않습니다.

C ++ 사양std:vector복용하는 생성자 count인수 (이 세 번째 폼의) 상태 :

`선택적으로 사용자 제공 할당 자 alloc을 사용하여 다양한 데이터 소스에서 새 컨테이너를 구성합니다.

3) 기본적으로 삽입 된 개수가 T 인 컨테이너를 구성합니다. 복사는 없습니다.

복잡성

2-3) 리니어 카운트

원시 배열에는이 초기화 비용이 발생하지 않습니다.

std :: vector <>를 피하여 모든 요소를 ​​초기화하는 방법을 참조하십시오 .


2

둘 사이의 성능 차이는 구현에 따라 크게 달라집니다. 잘못 구현 된 std :: vector를 최적의 배열 구현과 비교하면 배열이 이기지 만 돌아 서서 벡터가 이기게됩니다.

사과와 사과를 비교하는 한 (배열과 벡터 모두 고정 된 수의 요소를 갖거나 동적으로 크기가 조정되는 경우) STL 코딩 실습을 따르는 한 성능 차이는 무시할 만하다고 생각합니다. 표준 C ++ 컨테이너를 사용하면 표준 C ++ 라이브러리의 일부인 사전 롤 알고리즘을 사용할 수 있으며 대부분 자체 빌드 한 동일한 알고리즘의 평균 구현보다 성능이 더 우수합니다. .

즉, 적절한 디버그 모드를 사용하는 대부분의 STL 구현은 표준 컨테이너로 작업 할 때 사람들이 저지르는 전형적인 실수를 적어도 강조 표시 / 강화시킬 수 있기 때문에 IMHO는 디버그 STL로 디버그 시나리오에서 벡터가 승리합니다.

아, 그리고 배열과 벡터가 동일한 메모리 레이아웃을 공유하므로 벡터를 사용하여 기본 배열을 기대하는 레거시 C 또는 C ++ 코드로 데이터를 전달할 수 있습니다. 그러나이 시나리오에서는 대부분의 베팅이 해제되어 있으며 원시 메모리를 다시 다루고 있습니다.


1
성능 요구 사항 (O (1) 조회 및 삽입)을 충족하려면 동적 배열을 사용하여 std :: vector <> 을 거의 구현 해야 한다고 생각합니다. 확실히 이것이 확실한 방법입니다.
dmckee --- ex-moderator 고양이

성능 요구 사항뿐만 아니라 인접 저장소에 대한 요구 사항도 있습니다. 잘못된 벡터 구현은 배열과 API 사이에 너무 많은 간접 계층을 배치합니다. 좋은 벡터 구현은 인라인 코드, 루프에 사용되는 SIMD 등을 허용합니다.
Max Lybbert

설명 된 잘못된 벡터 구현은 표준을 준수하지 않습니다. 간접적으로 원한다면 std::deque사용할 수 있습니다.
Phil1970

1

동적으로 크기를 조정할 필요가 없으면 용량을 저장하는 데 메모리 오버 헤드가 생깁니다 (하나의 포인터 / size_t). 그게 다야.


1

인라인 함수 내부의 인라인 함수 내부에 벡터 액세스 권한이있는 경우가있을 수 있습니다. 인라인 함수 내부에서 컴파일러가 인라인하는 것을 넘어서고 함수 호출을 강제합니다. 걱정할 가치가 없을 정도로 일반적이지 않습니다. 일반적으로 저는 litb에 동의합니다 .

아직 아무도 언급하지 않은 것에 대해 놀랐습니다. 문제가 될 때까지 성능에 대해 걱정하지 말고 벤치마킹하십시오.


1

나는 주요 관심사는 성능이 아니라 안전이라고 주장한다. 벡터가 많은 고통을 덜어주는 배열 (예 : 크기 조정 고려)에 많은 실수를 할 수 있습니다.


1

벡터는 배열의 크기를 포함하기 때문에 배열보다 약간 더 많은 메모리를 사용합니다. 또한 프로그램의 하드 디스크 크기와 프로그램의 메모리 사용량을 증가시킵니다. 이러한 증가는 미미하지만 임베디드 시스템으로 작업하는 경우 중요 할 수 있습니다. 이러한 차이점이 중요한 대부분의 장소는 C ++ 대신 C를 사용하는 장소입니다.


2
이것이 중요한 경우에는 동적 크기의 배열을 사용하지 않는 것이므로 배열의 크기를 변경할 필요가 없습니다. (그렇다면 어떻게 든 크기를 저장하게 될 것입니다). 따라서 내가 실수하지 않으면 boost :: array를 사용할 수도 있습니다. 어딘가에 "크기 저장"이 필요하다고 말하는 이유는 무엇입니까?
Arafangion

1

다음과 같은 간단한 테스트 :

C ++ 어레이 대 벡터 성능 테스트 설명

"벡터 및 어레이 / 포인터에 대한 기본 인덱싱, 역 참조 및 증분 연산을 위해 생성 된 어셈블리 코드 비교"의 결론과 모순됩니다.

배열과 벡터간에 차이가 있어야합니다. 테스트는 그렇게 말합니다 ... 그냥 시도해보십시오. 코드가 있습니다 ...


1

때로는 배열이 실제로 벡터보다 낫습니다. 항상 고정 길이의 객체 집합을 조작하는 경우 배열이 더 좋습니다. 다음 코드 스 니펫을 고려하십시오.

int main() {
int v[3];
v[0]=1; v[1]=2;v[2]=3;
int sum;
int starttime=time(NULL);
cout << starttime << endl;
for (int i=0;i<50000;i++)
for (int j=0;j<10000;j++) {
X x(v);
sum+=x.first();
}
int endtime=time(NULL);
cout << endtime << endl;
cout << endtime - starttime << endl;

}

여기서 X의 벡터 버전은

class X {
vector<int> vec;
public:
X(const vector<int>& v) {vec = v;}
int first() { return vec[0];}
};

X의 배열 버전은 다음과 같습니다.

class X {
int f[3];

public:
X(int a[]) {f[0]=a[0]; f[1]=a[1];f[2]=a[2];}
int first() { return f[0];}
};

main ()의 배열 버전은 내부 루프에서 매번 "new"오버 헤드를 피하기 때문에 더 빠릅니다.

(이 코드는 comp.lang.c ++에 게시되었습니다.)


1

벡터를 사용하여 다차원 동작을 나타내는 경우 성능이 저하됩니다.

2d + 벡터가 성능 저하를 유발합니까?

요점은 크기 정보를 갖는 각각의 서브 벡터에 대해 적은 양의 오버 헤드가 있고, 데이터가 직렬화 될 필요는 없다는 점이다 (다차원 c 어레이가있는 것처럼). 이러한 직렬화 결여는 마이크로 최적화 기회보다 더 큰 기회를 제공 할 수 있습니다. 다차원 배열을 수행하는 경우 std :: vector를 확장하고 자체 get / set / resize 비트 함수를 롤링하는 것이 가장 좋습니다.


0

(예를 들어 고정 길이 배열을 가정 int* v = new int[1000];std::vector<int> v(1000);의 크기, v정말 중요한 것을 유일한 성능을 고려하여 1000 고정 된 상태로 유지되고) (또는 I 비슷한 딜레마에있을 때 나에게 중요 적어도) 액세스 속도는이다 요소. STL의 벡터 코드를 살펴본 결과 다음과 같습니다.

const_reference
operator[](size_type __n) const
{ return *(this->_M_impl._M_start + __n); }

이 함수는 컴파일러에 의해 가장 확실하게 인라인됩니다. 따라서으로 수행하려는 유일한 v요소는로 요소에 액세스하는 operator[]한 성능에 실제로 차이가 없어야하는 것처럼 보입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.