vector :: resize ()와 vector :: reserve () 중에서 선택


151

vector멤버 변수에 메모리를 미리 할당하고 있습니다. 아래 코드는 최소한의 부분입니다

class A {
  vector<string> t_Names;
public:
  A () : t_Names(1000) {}
};

이제 어느 시점에서 t_Names.size()같으면 1000. 크기를 (으)로 늘리려 고합니다 100. 그런 다음에 도달 1100하면 다시 증가 100합니다.

내 질문 사이에서 선택하는 것입니다 vector::resize()vector::reserve(). 이런 종류의 시나리오에서 더 나은 선택이 있습니까?

편집 :에 대한 정확한 견적이 t_Names있습니다. 나는 주변 700에 있다고 추정합니다 800. 그러나 특정 상황에서는 드물게 성장할 수 있습니다 1000.


34
이 작업을 수행하면 벡터 성장이 더 이상 일정 시간 동안 상각 되지 않으며 를 사용할 때의 성능 이점 중 하나가 손실 된다는 것을 알 수 있습니다 std::vector.
Blastfurnace

1
관련 사항 : C ++ 제작 용이성 : Dr. Dobbs 사이트에서 벡터가 어떻게 성장하는지 확인 하십시오.
jww

답변:


262

두 기능은 크게 다른 일을합니다!

resize()메소드는 (그리고 인자를 생성자에게 전달하는 것은 그것과 동등합니다) 벡터에 적절한 수의 요소를 삽입하거나 삭제하여 주어진 크기로 만듭니다 (값을 지정하기 위해 선택적인 두 번째 인수가 있습니다). 그것은 영향을 미치며 size(), 반복은 모든 요소를 ​​거치며, push_back은 그 뒤에 삽입되며를 사용하여 직접 액세스 할 수 있습니다 operator[].

reserve()메소드는 메모리 만 할당하지만 초기화되지 않은 상태로 둡니다. 에 영향 capacity()을 주지만 size()변경되지 않습니다. 벡터에 아무것도 추가되지 않기 때문에 객체에 대한 값이 없습니다. 그런 다음 요소를 삽입하면 미리 할당 되었기 때문에 재 할당이 발생하지 않지만 이것이 유일한 효과입니다.

그래서 그것은 당신이 원하는 것에 달려 있습니다. 기본 항목을 1000 개 배열하려면을 사용하십시오 resize(). 1000 개의 항목을 삽입 할 것으로 예상되는 배열을 원하고 두 개의 할당을 피하려면을 사용하십시오 reserve().

편집 : Blastfurnace의 의견에 따라 질문을 다시 읽고 이해했습니다. 귀하의 경우 정답이 수동으로 사전 할당되지 않습니다 . 필요할 때 요소를 계속 삽입하십시오. 벡터는 필요에 따라 자동으로 재 할당되며 언급 된 수동 방법보다 효율적으로 수행합니다 . reserve()이해하기 쉬운 유일한 경우 는 사전에 쉽게 구할 수있는 전체 크기를 합리적으로 정확하게 추정 할 때입니다.

EDIT2 : 광고 질문 수정 : 초기 견적이있는 경우 reserve()해당 견적입니다. 충분하지 않은 것으로 판명되면 벡터로 설정하십시오.


질문을 편집했습니다. 에 대한 특정 견적이 vector있습니다.
iammilind

3
@ Jan : 글쎄, 그것은 당신이 필요한 재산을 유지하기 위해 얼마나 힘들 었는지에 따라 깨지기 쉽거나 아닙니다. 같은 뭔가 x.reserve(x.size() + newdata); vector<int>::iterator special_element = get_special_element(x); for (int i = 0; i < newdata; ++i) { if some_function(i, special_element) x.push_back(i); }까지 공간을 확보 등에 관한 한 매우 강력합니다. 실제로 얼마나 많은 요소가 추가 될지 모르겠지만 상한이 있습니다. 물론 의심스러운 경우 벡터를 사용하면 반복자 대신 인덱스를 사용할 수 있지만 그 차이는 대개 무시할 수 있습니다.
Steve Jessop

4
당신의 말은 이미 정답을 알고있는 누군가에게는 의미가 있지만 질문을해야하는 사람들을 쉽게 오도 할 수 있습니다. "resize () ...는 주어진 수의 요소를 벡터에 삽입합니다"-처음 사용될 때만 true-일반적으로 요청 된 수와 기존의 차이를 삽입합니다 size(). "reserve () 메소드는 메모리 만 할당합니다"- capacity()이미 충분한 지 여부에 따라 메모리를 할당하거나 할당하지 않을 수 있으며 요소를 이동하고 원래 메모리를 할당 해제해야 할 수도 있습니다. "두 개의 할당을 피하고 싶다"및 사본 등
Tony Delroy

19
실제로, 푸시하기 전에 예약하는 것이 중요하며 사용해야합니다. 어떤 종류의 3D 모델 로더를 코딩하고 있고 모델의 정점이 15000이라고 가정합니다. 먼저 사전 할당하지 않고로드하는 동안 각 정점을 푸시 _ 백하려고하면 시간이 오래 걸립니다. 나는 개인적으로 거의 100000 개의 정점이있는 자동차 .obj 모델을로드하려고 시도했지만 30 초가 걸렸습니다. 그런 다음 .reserve ()와 함께 사전 할당을 사용하여 코드를 리팩터링했습니다. 이제 3 초가 걸립니다. 코드의 시작 부분에 .reserve (100000)을 넣으면 27 초가 절약됩니다.
deniz

1
@deniz 100000 규모에서는 그다지 사실이 아니지만 100-300 규모에서는 그다지 사실이 아닙니다. 불필요하게 수행하면 예약이 낭비 될 수 있습니다.
deworde

30

resize()메모리를 할당 할 뿐만 아니라 인수로 전달할 원하는 크기 만큼의 인스턴스를 만듭니다 . 그러나 메모리 만 할당하고 인스턴스를 만들지 않습니다. 그건,resize()reserve()

std::vector<int> v1;
v1.resize(1000); //allocation + instance creation
cout <<(v1.size() == 1000)<< endl;   //prints 1
cout <<(v1.capacity()==1000)<< endl; //prints 1

std::vector<int> v2;
v2.reserve(1000); //only allocation
cout <<(v2.size() == 1000)<< endl;   //prints 0
cout <<(v2.capacity()==1000)<< endl; //prints 1

출력 ( 온라인 데모 ) :

1
1
0
1

따라서 resize()기본 생성 객체를 원하지 않으면 바람직하지 않을 수 있습니다. 느려질 것입니다. 또한 push_back()새 요소를 size()추가하면 새 메모리를 할당 하여 벡터의 벡터가 더 증가 합니다 (이는 기존 요소를 새로 할당 된 메모리 공간으로 이동 함을 의미 함). 당신이 사용하는 경우 reserve()이미 충분히 할당 된 메모리가 확인하기 위해 시작시, size()벡터의 때 당신 증가 할 것이다 push_back()그것, 그러나 당신이 그것을 위해 예약 된 공간이 부족 때까지 다시 새로운 메모리를 할당하지 않습니다 .


6
하고 나면 무해하게 reserve(N)사용할 수 있습니다 operator []. 맞습니까?
iammilind

2
대부분의 구현은 사용자가 요청한 정확한 양을 할당하지만 reserve사양은 최소한 그 정도만 할당하면되므로 일부 구현은 일부 경계로 반올림하여 1000보다 높은 용량을 표시 할 수 있습니다.
Jan Hudec

16
@iammilind : 아니요, 인덱스가보다 크거나 같은 경우 v.size(). 참고 reserve(N)변경되지 않습니다 size()벡터의.
Nawaz

5
@iammilind : 잘못되었습니다. reSERVE를 호출 한 후에는 항목이 추가되지 않고 추가 할 수있는 충분한 메모리 만 확보됩니다.
Jan Hudec

2

설명에서 벡터 t_Names의 할당 된 저장 공간을 "예약"하려는 것 같습니다.

단지 할당하지만 구성하지 않는 resize새로 할당 된 벡터 를 초기화합니다 reserve. 따라서 '예약'은 '크기 조정'보다 훨씬 빠릅니다.

크기 조정예약 차이에 관한 설명서를 참조 할 수 있습니다


1
대신 여기를 참조하십시오 : 벡터용량 ( 왜? )
sehe

1
링크를 추가해 주셔서 감사합니다. sehe
dip

2

예약시 객체를 초기화하지 않으려면 예약하십시오. 또한 크기를 조정할 때 사용 횟수와 사용 횟수를 논리적으로 구분하고 추적하는 것이 좋습니다. 따라서 인터페이스에는 동작상의 차이가 있습니다. 벡터는 예약 된 경우 동일한 수의 요소를 나타내며 시나리오에서 크기를 조정하면 100 개의 요소가 커집니다.

이런 종류의 시나리오에서 더 나은 선택이 있습니까?

기본 행동과 싸울 때 당신의 목표에 전적으로 달려 있습니다. 어떤 사람들은 커스터마이즈 된 할당 자들을 선호 할 것입니다. 그러나 우리는 당신이 잘 조언하기 위해 프로그램에서 무엇을 해결하려고하는지 더 잘 알고 있어야합니다.

fwiw, 많은 벡터 구현은 할당 요소 수를 늘려야 할 때 단순히 할당 요소 수를 두 배로 늘릴 것입니다. 최대 할당 크기를 최소화하려고합니까?


" 예약 될 때 객체를 초기화하지 않으려면 예약하십시오. "올바른 공식은 객체가 존재 하지 않도록하려는 경우 입니다. 객체를 읽을 수는 없지만 할당 할 수있는 간단하게 구성 가능한 형식의 초기화되지 않은 배열과는 다릅니다. 오히려 메모리 만 예약되어 있지만 메모리에 객체가 없으므로 다른 방법으로 액세스 할 수 없습니다 operator[].
underscore_d
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.