C++에서 루프 없이 배열의 내용을 std::벡터에 어떻게 복사합니까?

StackOverflow https://stackoverflow.com/questions/259297

  •  06-07-2019
  •  | 
  •  

문제

나중에 처리하기 위해 저장해야 하는 프로그램의 다른 부분에서 내 함수로 전달되는 값 배열이 있습니다.데이터를 처리하는 시간이 되기 전에 내 함수가 몇 번 호출될지 모르기 때문에 동적 저장 구조가 필요해서 선택했습니다. std::vector.나는 표준 루프를 수행하고 싶지 않습니다. push_back 모든 값을 개별적으로 복사할 수 있다면 다음과 유사한 것을 사용하여 모두 복사할 수 있다면 좋을 것입니다. memcpy.

도움이 되었습니까?

해결책

배열과 배열 크기를받은 후 벡터를 구성 할 수 있다면 다음과 같이 말할 수 있습니다.

std::vector<ValueType> vec(a, a + n);

... 가정 a 당신의 배열입니다 n 포함하는 요소의 수입니다. 그렇지 않으면, std::copy() w/resize() 트릭을 할 것입니다.

나는 멀리 떨어져있을 것입니다 memcpy() 값이 평범한 오래된 데이터 (POD) 유형인지 확인할 수 없다면.

또한, 이것들 중 어느 것도 실제로 루프를 피하는 것을 피할 수 없다는 점은 주목할 가치가 있습니다. 그것은 당신이 당신의 코드에서 그것을 볼 수 있는지 여부에 대한 질문 일뿐입니다. o (n) 런타임 성능은 값을 복사 할 수 없습니다.

마지막으로, C 스타일 어레이는 대부분의 STL 알고리즘에 완벽하게 유효한 컨테이너입니다. 원시 포인터는 begin(), 그리고 (ptr + n)와 같습니다 end().

다른 팁

여기에는 많은 답이 있었고 거의 모든 사람들이 일을 끝낼 것입니다.

그러나 오해의 소지가있는 조언이 있습니다!

다음은 다음과 같습니다.

vector<int> dataVec;

int dataArray[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
unsigned dataArraySize = sizeof(dataArray) / sizeof(int);

// Method 1: Copy the array to the vector using back_inserter.
{
    copy(&dataArray[0], &dataArray[dataArraySize], back_inserter(dataVec));
}

// Method 2: Same as 1 but pre-extend the vector by the size of the array using reserve
{
    dataVec.reserve(dataVec.size() + dataArraySize);
    copy(&dataArray[0], &dataArray[dataArraySize], back_inserter(dataVec));
}

// Method 3: Memcpy
{
    dataVec.resize(dataVec.size() + dataArraySize);
    memcpy(&dataVec[dataVec.size() - dataArraySize], &dataArray[0], dataArraySize * sizeof(int));
}

// Method 4: vector::insert
{
    dataVec.insert(dataVec.end(), &dataArray[0], &dataArray[dataArraySize]);
}

// Method 5: vector + vector
{
    vector<int> dataVec2(&dataArray[0], &dataArray[dataArraySize]);
    dataVec.insert(dataVec.end(), dataVec2.begin(), dataVec2.end());
}

벡터 :: 삽입을 사용하는 긴 이야기 짧은 방법 4를 자르려면 BSRUTH의 시나리오에 가장 적합합니다.

다음은 몇 가지 세부 사항입니다.

방법 1 아마도 이해하기 가장 쉬운 일입니다. 배열에서 각 요소를 복사하고 벡터 뒷면으로 밀어 넣으십시오. 아아, 느린다. 루프가 있기 때문에 (사본 함수와 암시) 각 요소는 개별적으로 처리되어야합니다. 배열과 벡터가 인접한 블록이라는 것을 알고 있다는 사실을 바탕으로 성능 개선이 이루어질 수 없습니다.

방법 2 방법 1에 대한 제안 된 성능 개선; 추가하기 전에 배열의 크기를 사전 보충하십시오. 큰 배열의 경우 이것 ~할 것 같다 돕다. 그러나 프로파일 링이 개선을받을 수 없다고 제안하지 않는 한 가장 좋은 조언은 절대 예비를 사용하지 않는 것입니다 (또는 반복자가 무효화되지 않도록해야합니다). Bjarne은 동의합니다. 덧붙여서, 나는이 방법이 수행되었다는 것을 발견했다 가장 느린 대부분의 경우, 나는 그것이 정기적으로 왜 있었는지 종합적으로 설명하기 위해 고군분투하고 있습니다. 중요하게 방법 1보다 느립니다 ...

방법 3 구식 솔루션입니다 - 문제에 C를 던져! 포드 유형에 대해 잘 작동합니다. 이 경우 Memcpy는 벡터의 범위 외부에서 작동하기 때문에 크기가 호출되어야하며 크기가 바뀌 었음을 벡터에게 알리는 방법이 없습니다. 추악한 솔루션 (바이트 복사!) 이외에도 포드 유형에만 사용됩니다. 나는이 솔루션을 사용하지 않을 것입니다.

방법 4 가는 가장 좋은 방법입니다. 의미가 분명합니다. (보통) 가장 빠르며 모든 객체에 대해 작동합니다. 이 응용 프로그램 에이 방법을 사용하는 데는 단점이 없습니다.

방법 5 메소드 4에서 조정 - 배열을 벡터에 복사 한 다음 추가하십시오. 좋은 선택 - 일반적으로 빠르고 명확합니다.

마지막으로, 배열 대신 벡터를 사용할 수 있다는 것을 알고 있습니까? 함수가 C 스타일 배열을 기대하더라도 벡터를 사용할 수 있습니다.

vector<char> v(50); // Ensure there's enough space
strcpy(&v[0], "prefer vectors to c arrays");

그것이 누군가를 도울 수 있기를 바랍니다!

당신이하고있는 모든 일이 기존 데이터를 대체하는 것만이라면이 작업을 수행 할 수 있습니다.

std::vector<int> data; // evil global :)

void CopyData(int *newData, size_t count)
{
   data.assign(newData, newData + count);
}

std :: 사본 당신이 찾고있는 것입니다.

내 답변만 편집할 수 있으므로 내 질문에 대한 다른 답변을 종합하여 답변을 만들겠습니다.답변해주신 모든 분들께 감사드립니다.

사용 표준::복사, 이는 여전히 백그라운드에서 반복되지만 코드를 입력할 필요는 없습니다.

int foo(int* data, int size)
{
   static std::vector<int> my_data; //normally a class variable
   std::copy(data, data + size, std::back_inserter(my_data));
   return 0;
}

일반 사용 밈피.이는 아마도 기본 데이터 유형(예:int) 하지만 더 복잡한 구조체나 클래스 배열에는 해당되지 않습니다.

vector<int> x(size);
memcpy(&x[0], source, size*sizeof(int));
int dataArray[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };//source

unsigned dataArraySize = sizeof(dataArray) / sizeof(int);

std::vector<int> myvector (dataArraySize );//target

std::copy ( myints, myints+dataArraySize , myvector.begin() );

//myvector now has 1,2,3,...10 :-)

memcpy를 피하십시오. 당신이 실제로 필요하지 않으면 포인터 작업을 엉망으로 만들 이유가 없습니다. 또한 POD 유형 (예 : int)에서만 작동하지만 구조가 필요한 유형을 다루는 경우에는 실패합니다.

위에 제시된 방법 외에도 std :: vector.reserve (), std :: vector.resize ()를 사용하거나 벡터를 크기로 구성하여 벡터가 충분한 요소가 있는지 확인해야합니다. 데이터를 보유합니다. 그렇지 않다면 메모리가 손상 될 것입니다. 이것은 std :: copy () 또는 memcpy ()에 해당됩니다.

이것이 Vector.push_back ()을 사용하는 이유입니다. 벡터의 끝을 지나서는 글을 쓸 수 없습니다.

또 다른 대답은 그 사람이 "내 함수가 몇 번이라고 불리는지 모르겠다"고 말했기 때문에 벡터 삽입 메소드를 사용하여 값의 배열을 벡터 끝에 추가 할 수 있습니다.

vector<int> x;

void AddValues(int* values, size_t size)
{
   x.insert(x.end(), values, values+size);
}

벡터의 구현은 반복자 유형과 유형 자체를 기반으로 값을 삽입하는 가장 좋은 방법을 최적화 할 수 있기 때문에 이런 방식이 마음에 듭니다. 당신은 STL의 구현에 대해 다소 응답하고 있습니다.

가장 빠른 속도를 보장해야하고 유형이 포드 유형이라는 것을 알고 있다면 Thomas의 답변에서 크기 조정 방법을 권장합니다.

vector<int> x;

void AddValues(int* values, size_t size)
{
   size_t old_size(x.size());
   x.resize(old_size + size, 0);
   memcpy(&x[old_size], values, size * sizeof(int));
}

벡터의 항목이 얼마나 큰지 알고 있다고 가정합니다.

std::vector<int> myArray;
myArray.resize (item_count, 0);
memcpy (&myArray.front(), source, item_count * sizeof(int));

http://www.cppreference.com/wiki/stl/vector/start

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top