2012-07-10 2 views
0

내 벡터에 팩토리 함수를 사용하고 이전 값을 부는 resize를 호출하지 않고 반복기를 사용하고 싶습니까?std :: vector에 .resize()없이 유효한 .begin() 및 .end()를 사용하는 방법?

STL 디자인에서 요점이 누락되었거나 없습니까?

#include <vector> 
#include <algorithm> 
#include <iostream> 

struct A 
{ 
    A():_x(42){} 
    A(double x):_x(x){} 
    double _x; 
}; 

struct factory 
{ 
    A operator()() 
    { 
     return A(3.14); 
    } 
}; 

int main() 
{ 
    std::vector<A> v; 
    int nbr = 3; 
    v.reserve(nbr); 
    std::generate_n(v.begin(), nbr, factory()); 

    std::cout << "Good values" << std::endl; 
    for(int i = 0 ; i < nbr ; ++i) 
     std::cout << v[i]._x << std::endl; 

    v.resize(nbr); //How I can have the syntax below without the resize which blows my previous values ? 

    std::cout << "resize has been called so values are bad (i.e default ctor)" << std::endl; 
    for(std::vector<A>::iterator it = v.begin() ; it != v.end() ; ++it) 
     std::cout << (*it)._x << std::endl; 
} 

감사합니다 :)

답변

8

나는 당신의 우려를 이해하지 못했거나 오해의 소지가있었습니다. resize()은 컨테이너의 기존 요소를 수정하지 않습니다 (작은 크기로 크기를 조정하면 제거 된 요소 제외).

이제 실제 문제는 프로그램에서 정의되지 않은 동작이 있다는 것입니다. generate_n을 호출하면 벡터의 문자는 capacity() == nbr이지만 size() == 0이며이 문자는 컨테이너의 끝 부분을 넘어서서 쓰여지고 있습니다.

std::vector<A> v; 
int nbr = 3; 
v.resize(nbr); 
std::generate_n(v.begin(), nbr, factory()); 

아니면 당신은 반복자의 유형을 변경할 수 있습니다 : 두 가지 솔루션은 먼저 generate_n를 호출 전에 의 크기를 조정할 수 있습니다,이위한

std::vector<A> v; 
int nbr = 3; 
v.reserve(nbr); 
std::generate_n(std::back_inserter(v), nbr, factory()); 
+0

감사합니다. back_inserter 이터레이터와 그 속성을 완전히 잊었습니다. :) – Quanteek

0
v.reserve(nbr); 
std::generate_n(v.begin(), nbr, factory()); 

그것은`오류입니다. Reserve! = resize, 필요한 경우에만 메모리를 할당하십시오. 인쇄 벡터에 크기를 사용하는 이유는 무엇입니까? 크기 조정 벡터, begin/end가 크기 조정에 종속되지 않는 기능입니다. ...

0

generate_n은 벡터에 값을 올바르게 생성하지 않습니다. 벡터의 크기는 0이므로 제대로 작동하는 것처럼 보일 수도 있지만, 벡터의 끝을 넘어 쓸 때 운이 좋을 것입니다. 실제로는 resize 또는 그와 비슷한 것을 사용해야합니다. 번갈아서 (그리고 더 많은 공연자가) back_inserter을 사용할 수 있습니다. std::generate_n(std::back_inserter(v), nbr, factory());

0

코드의 첫 번째 부분은 이미를 부서진. 벡터 요소를 생성하려면 이 아니라 resize을 호출해야합니다. reserve은 원시 메모리를 할당하여 향후 벡터 용량 만 예약 할 수 있지만 실제 벡터 요소는 생성 (생성)하지 않습니다. 일반적으로 벡터의 크기와 벡터의 용량 사이에있는 벡터 요소에 액세스 할 수 없습니다.

당신은 reserve을 호출 했으므로 요소가 이미 생성 된 것처럼 벡터를 사용하려고합니다. 값을 할당하고이 값을 읽고 인쇄하려고 시도합니다. 일반적으로 이것은 불법이며 일반적으로 정의되지 않은 동작을 초래합니다. 그 사이에 벡터의 크기는 0으로 남았습니다. 이는 나중에 resize으로 전화를 걸어 보충 한 것입니다.

처음에는 resize으로 전화해야합니다. 처음부터 적절한 수의 요소를 사용하여 벡터를 만듭니다. (초기 크기를 벡터의 생성자에 전달하여이 작업을 수행 할 수도 있습니다).

예를 들어, 당신이

int nbr = 3; 
std::vector<A> v(nbr); 
std::generate_n(v.begin(), nbr, factory()); 

또는

std::vector<A> v; 
int nbr = 3; 
v.resize(nbr); 
std::generate_n(v.begin(), nbr, factory()); 

과를 완료 할. reserve에 대해 잊어 버려 -이 경우에는 필요하지 않습니다.

관련 문제