2013-08-10 2 views
2

이것은 아마도 간단한 문제 일뿐입니다. 그러나 이것은 많은 혼란을 야기합니다.C++ 11 - 반복자로 함수에서 벡터 전달하기

나는 채워진 벡터를 반환하는 클래스 멤버가 :

vector<double> returnVector() 
{ 
    return theVector; 
} 

내가 전달 된 값의 유형을 교대 할 수 있도록 나는 또한 Iterator를 받아 toArray()을 호출되는 함수가 예를 들면 다음과 같습니다.

template<typename T, typename Inverse> 
T* toArray(Inverse begin, Inverse end) 
{ 
    size_t size = distance(begin, end); 
    auto pos = 0; 

    T* tmp = new T[size]; 

    for(auto i = begin; i != end; i++) 
    { 
     tmp[pos] = *i; 
     pos++; 
    } 
    return tmp; 

} 

나는 내 생각에 다음을 할 수있을 것이라고 생각했습니다.

MyClass class; 

auto* var = Functs::toArray<double>(
       std::begin(class.returnVector()), 
       std::end(class.returnVector()) 
      ); 

이 있지만, 일을하고 나는 약간의 malloc 오류가 발생하지 않는 것. 그러나 다음을 수행 할 수 있습니다.

MyClass class; 

vector<double> vals = class.returnVector(); 
auto* var = Functs::toArray<double>(
    std::begin(vals), 
    std::end(vals) 
); 

왜 이런 일이 발생하는지 설명 할 수 있습니까? 나는 함수 returnVector이 실제 벡터를 반환하기 때문에 begin에서 end으로 액세스 할 수 있다는 가정하에 있었습니까?

+1

문제와 관련이 없지만 'returnVector' 함수가 벡터의 * copy *를 반환한다는 것을 기억하십시오. 참조 (또는 아마도 'const' 참조)를 반환 할 수 있습니다. –

+1

당신의 문제에 관해서는, 런타임 에러 인 것처럼 프로그램을 디버거에서 먼저 실행하여 에러를 찾아야합니다. 그런 다음 실제 오류에 대해 더 많은 코드를 제공하고 가능한 충돌의 호출 스택을 제공하는 등 오류에 대해 자세히 설명해야합니다. –

+0

@JoachimPileborg 나는 'std :: bad_alloc'의 인스턴스를 던진 후에'terminate '를 호출하는 것처럼 보입니다. what() : std :: bad_alloc 트랩을 중단합니다 : 6' 디버깅을 시도합니다. 'std :: distance (begin, end);'숫자는 원래보다 길어야합니다. – Phorce

답변

3
다음

: 값을 기준으로

Functs::toArray<double>(
    std::begin(class.returnVector()), 
    std::end(class.returnVector()) 
); 

당신의 returnVector 메소드가 리턴, 그래서 당신은 사본을 얻을. 즉, 두 개의 호출이 다른 벡터를 생성합니다. 이것이 예상보다 훨씬 넓은 범위를 차지하는 이유와 잘못된 메모리에 액세스하는 이유입니다.

가능한 경우 returnVector을 변경하여 참조를 반환하십시오. 그러나 이것이 옵션이 아니라면 다른 예제처럼 로컬 참조를 항상 저장해야한다는 것을 기억해야합니다.

또 다른 옵션은 편의 과부하를 정의하는 것입니다 :

template<typename T> 
T* toArray(std::vector<T>& vec) { 
    return toArray(std::begin(vec), std::end(vec)); 
} 

이 같이 호출 할 수있는 :

auto* var = Functs::toArray(class.returnVector()); 

가 개인적으로 나는 그 옵션을 갈 것입니다. endbegin [iterator.requirements.general]에서 (항상)에 도달 할 수없는 경우

+0

흠, 실제로 2 개의 오버로드를 만들어야 할 수도 있습니다 :'T * toArray (const T & vec)'와'T * toArray (T && vec)'(후자는 C++ 11이 필요합니다). 그러나 나는 확실히 모른다. 그것은 내 머리 꼭대기에서 기억할 수없는 방식으로'returnVector'의 리턴 타입에 달려 있습니다. YMMV와 그 모든 것. – Dave

+0

OP는 기본적으로'std :: vector :: data'를 리메이크하고 있습니다. – Rapptz

+0

@Rapptz 네, 그렇습니다. 그러나 나는 의심의 이익을 줄 것이며 이것이 반복자로 실제로하고 싶은 것의 단순화 된 예라고 가정합니다. – Dave

2

귀하의 코드

size_t size = distance(begin, end); 

정의되지 않은 동작을 일으 킵니다. toArray을 사용하는 첫 번째 예제의 경우입니다. 두 번째 예가 유효합니다.

당신이 returnVector

vector<double> const& returnVector() const; 

을 변경하지 않고 사용 일반적으로

vector<double>::data(); 

toArray보다 당신이 할당 된 데이터에 원시 포인터를 반환하지 않도록하는 경우, 그것은 최선의 경우가 더 낫다.

관련 문제