2012-04-18 2 views
11

기존의 vector 요소의 복사본을 두 번 삽입하려고합니다. 다음 코드는 이전 버전에서 작동하지만, 2010 년중복 요소를 벡터에 삽입하는 방법은 무엇입니까?

#include <iostream> 
#include <vector> 

using namespace std; 

int main(int argc, char* argv[]) 
{ 
    vector<int> test; 
    test.push_back(1); 
    test.push_back(2); 
    test.insert(test.begin(), test[0]); 
    cout << test[0] << " " << test[1] << " " << test[2] << endl; 
    return 0; 
} 

출력이 -17891602 1 2입니다 비주얼 스튜디오에 실패 1 1 2을 기대했다.

나는 그것이 일어나는 이유를 알아 냈습니다. 벡터가 재 할당되고 참조 점이 삽입 점에 복사되기 전에 유효하지 않게됩니다. 오래된 Visual Studio는 분명히 다른 순서로 작업을 수행 했으므로 정의되지 않은 동작의 한 가지 가능한 결과는 올바르게 작동하는 것임을 입증하고 의존할만한 것이 아님을 증명합니다.

이 문제를 해결하기위한 두 가지 방법이 있습니다.

template<typename T> 
T make_copy(const T & original) 
{ 
    return original; 
} 

    test.insert(test.begin(), make_copy(test[0])); 

비록 : 다른 유효한 남아있는 기준에 종속가 없습니다 있도록 참조에서 복사본을 만드는 것입니다

test.reserve(test.size() + 1); 
    test.insert(test.begin(), test[0]); 

: 하나는 더 재 할당이 발생하지 있는지 확인 reserve을 사용하는 것입니다 둘 다 작동하지만 어느 누구도 자연스러운 해결책을 느끼지 못합니다. 내가 빠진 것이 있습니까?

+0

BTW vc11 dev 미리보기의 첫 번째 예는 '1 2 2'입니다. –

+0

@ 제시, 놀라지 않습니다. '삽입 (insert)'의 Rvalue 과부하가 선택되어 버그로 수정되었을 수 있습니다. 코드는 그 오버로드와 const 참조를 취하는 것과 완전히 다릅니다. –

+0

int로 캐스팅을 수행합니까? –

답변

1

나는 이것이 동작이라고 생각합니다. 2011 C++ 표준의 §23.2.3에서 테이블 100은 시퀀스 컨테이너 요구 사항을 나열하고이 경우 항목이 있습니다. 이는 예시적인 표현을 aT의 요소를 포함하는 서열 컨테이너 타입이 X의 값이

a.insert(p,t) 

를 제공 pa에 CONST 반복자이며 tX::value_type의 좌변 또는 CONST r- 수치이며 즉 T입니다.

이 식의 주장이다

이 필요합니다TXCopyInsertable이어야한다. vectordeque의 경우 TCopyAssignable이어야합니다.
효과 :t 사본을 p 앞에 삽입합니다.

비고 : 새로운 사이즈가 기존 용량보다 큰 경우 재 할당 원인 내가 찾을 수

유일한 관련 벡터 특정 인용 §23.3.6.5 제 1 항에있다. 재 할당이 발생하지 않으면 삽입 점 이전의 모든 반복기와 참조가 유효합니다.

벡터가 다시 할당되는 것을 언급하지만, 시퀀스 컨테이너의 이전 요구 사항 인 insert을 예외로하지 않습니다.

이 문제를 해결하기 위해 @EdChum의 요소 사본을 만들고 그 사본을 삽입하는 제안에 동의합니다.

+0

't '가'a '의 멤버에 대한 참조 인 경우를 호출하는 설명에 아무것도 표시되지 않습니다. –

4

vector::insert은 값이 아닌 두 번째 매개 변수로 값을 참조합니다. 템플릿을 복사 할 필요가 없습니다. 복사 생성자를 사용하여 참조로 전달되는 다른 객체를 만듭니다. 이 사본은 벡터 크기를 조정하더라도 유효합니다.

#include <iostream> 
#include <vector> 

using namespace std; 

int main(int argc, char* argv[]) 
{ 
    vector<int> test; 
    test.push_back(1); 
    test.push_back(2); 
    test.insert(test.begin(), int(test[0])); 
    cout << test[0] << " " << test[1] << " " << test[2] << endl; 
    return 0; 
} 
+0

이것은 테스트 케이스에 불과합니다. 내 실제 코드에는 int보다 훨씬 복잡한 요소가 포함되어 있으며 임시 생성자는 추악해진다. 그래도 좋은 제안. –

관련 문제