한 벡터를 다른 벡터로 복사하는 빠른 방법


155

나는 두 가지 방법을 선호합니다 :

void copyVecFast(const vec<int>& original)
{
  vector<int> newVec;
  newVec.reserve(original.size());
  copy(original.begin(),original.end(),back_inserter(newVec));
}

void copyVecFast(vec<int>& original)
{

  vector<int> newVec;
  newVec.swap(original); 
}

어떻게합니까?


14
두 번째 이름은 사본이 아니기 때문에 오해의 소지가 있습니다.
Anonymous

답변:


126

참조로 인수를 보내면 두 번째 예가 작동하지 않습니다. 를 의미 한거야

void copyVecFast(vec<int> original) // no reference
{

  vector<int> new_;
  new_.swap(original); 
}

작동하지만 더 쉬운 방법은

vector<int> new_(original);

잘 작동합니다. 그러나 벡터 배열에서는 작동하지 않습니다. 예 : vector <int> A [n];
ABcDexter

8
그것은 복사가 아니라 스왑입니다.
sdd

1
@ sdd-아닙니다. 인수 목록을 확인하십시오. original함수 인수의 사본입니다.
rlbond

249

그들은 같지 않습니까? 하나는 사본이고 다른 하나는 스왑 입니다. 따라서 함수 이름입니다.

내가 가장 좋아하는 것은 :

a = b;

어디에 a그리고 b벡터입니다.


3
실제로이 접근 방식은 값으로 전달되고 컴파일러는 복사 생성자를 호출 한 다음 새로 생성 된 요소를 교체합니다. rlbond가 동일한 효과를 얻기 위해 복사 생성자를 직접 호출 할 것을 제안하는 이유입니다.
David Rodríguez-dribeas

1
그러나 원본을 val로 전달하는 함수가 없으면 rlbon을 호출 할 수 없습니다. 그렇지 않으면 원본이 비게됩니다. 두 번째 솔루션은 항상 가치를 기준으로 전화하므로 원래 벡터의 날짜를 잃지 않도록합니다. (스왑이 포인터를 처리한다고 가정)
Eyad Ebrahim

b의 요소를 a로 옮기지 않습니까 (b = 크기가 0 인 채로두기)?
조나단.

1
@홍옥. 당신이 a = b다음 에 대해 이야기하고 있다고 가정하면 아니오. 할당 수단 : 변경하지 않고 a동등하게 만듭니다 . 대조적으로, 내용을 교환 할 것입니다 (따라서 이전 의 내용 이 될 것입니다 ). 아마도 C ++ 11에서와 같이 이동 작업을 생각하고 있지만 이와 같은 일반적인 할당에서는 아닙니다. 이러한 움직임은 떠날 것이다 에, 에헴 "흥미로운"상태 - 볼 stackoverflow.com/questions/17730689/...을bbstd::swap(a, b)bsizeab
다니엘 Earwicker을

1
@홍옥. 이중 앰퍼샌드에 유의하십시오 &&. 이 버전은 rvalue 참조에만 사용됩니다. 상수가 아닌 값과 일치하지 않습니다 (예 b: 위의 예와 같이). 더 복잡한 수준에 대해서는 en.cppreference.com/w/cpp/language/value_category 를 참조 b하여 하나로 바꿀 수 있습니다 . a = std::move(b);
Daniel Earwicker

74

이것은 벡터의 복사본을 만드는 또 다른 유효한 방법입니다. 생성자를 사용하십시오.

std::vector<int> newvector(oldvector);

이것은 std::copy전체 벡터를 처음부터 끝까지 std::back_insert새 벡터로 옮길 때 사용 하는 것보다 훨씬 간단 합니다.

즉, .swap()하나는 사본이 아니며 대신 두 벡터를 바꿉니다. 더 이상 아무것도 포함하지 않도록 원본을 수정하십시오! 사본이 아닙니다.


19

직접 답변 :

  • =연산자 사용

벡터의 값을 다른 값으로 할당하기 위해 std::vector::operator=컨테이너 의 public 멤버 함수 를 사용할 수 있습니다 std::vector.

  • 생성자 함수 사용

게다가 생성자 함수도 의미가 있습니다. 매개 변수로 다른 벡터를 가진 생성자 함수 (예 :xx 는의 순서대로 각 요소의 복사본이있는 컨테이너를 구성합니다 .

주의:

  • 사용하지 마세요 std::vector::swap

std::vector::swap벡터를 다른 벡터로 복사 하지 않고 이름에서 알 수 있듯이 실제로 두 벡터의 요소를 교체합니다. 다시 말해, 복사 할 소스 벡터 std::vector::swap가 호출 된 후 수정 됩니다. 이는 아마도 예상과 다릅니다.

  • 깊거나 얕은 사본?

소스 벡터의 요소가 다른 데이터에 대한 포인터 인 경우 때로는 딥 카피가 필요합니다.

Wikipedia에 따르면 :

딥 카피는 필드가 역 참조됨을 의미합니다. 복사중인 객체에 대한 참조가 아니라 참조 된 객체에 대해 새로운 복사 객체가 생성되며이 객체에 대한 참조는 B에 배치됩니다.

실제로 현재 C ++에는 딥 카피를 수행하는 기본 제공 방법이 없습니다. 위에서 언급 한 모든 방법은 얕습니다. 딥 카피가 필요한 경우 벡터를 탐색하고 참조 사본을 수동으로 만들 수 있습니다. 또는 순회를 위해 반복자가 고려 될 수 있습니다. 반복자에 대한 토론은이 질문을 넘어선 것입니다.

참고 문헌

std::vectorcplusplus.com 의 페이지


14

스왑을 사용하여 벡터를 복사하면 안되며 "원본"벡터가 변경됩니다.

대신 원본을 매개 변수로 새 매개 변수로 전달하십시오.


14
new_vector.assign(old_vector.begin(),old_vector.end()); // Method 1
new_vector = old_vector; // Method 2

-14

벡터가 이미 존재하고 방금 복사하려는 경우 다음을 수행 할 수 있습니다.

newVec.resize(oldVec.size());
memcpy(&newVec.at(0), &oldVec.at(0), oldVec.size());

1
memcpy하지 마십시오. memcpy가 바이트 단위의 크기를 사용하기 때문에 이것은 작동하지 않습니다. 또한 다른 벡터가 이미 존재하면 newVec = oldVec다른 답변 중 하나와 동일한 것을 수행 할 수 있습니다 .
FDinoff

네, 맞아요. 나는 그것을 보지 못했다. @ FDinoff는 아래의 방법 중 하나라도 작동하지만 왜 memcpy를 사용하지 않는 것이 좋습니다? newVec = oldVec보다 훨씬 빠릅니다. memcpy (& newVec.at (0), & oldVec.at (0), oldVec.size () * sizeof (int));
sgowd

1
일반적인 경우 복사 생성자를 호출하지 않고 객체를 복사하면 미묘한 버그가 발생할 수 있습니다. 이 경우 나는 그들이 같은 성능을 가질 것이라고 생각했을 것입니다. 그것이 아니라면 vector가 이미 최적화되어 있지 않다고 말할 것입니다. 실제로 벤치 마크를 작성 했습니까?
FDinoff

나는 당신을 비난하지 않았습니다. 우리 팀장도 같은 것을 제안했고 이해하려고 노력했습니다.
sgowd

(나는 당신이 나를 비판하고 있다고 생각하지 않았습니다.) 아직도 이해하지 못하는 것이 있습니까?
FDinoff
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.