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


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.