Jak skopiować zawartość tablicy do std:: vector w C++ bez zapętlania?
Mam tablicę wartości, która jest przekazywana do mojej funkcji z innej części programu, którą muszę zapisać do późniejszego przetworzenia. Ponieważ Nie wiem, ile razy moja funkcja zostanie wywołana, zanim nadejdzie czas przetwarzania danych, potrzebuję dynamicznej struktury pamięci masowej, więc wybrałem std::vector
. Nie chcę wykonywać standardowej pętli do push_back
wszystkich wartości indywidualnie, byłoby miło, gdybym mógł skopiować to wszystko używając czegoś podobnego do memcpy
.
10 answers
Jeśli możesz skonstruować wektor po uzyskaniu tablicy i rozmiaru tablicy, możesz po prostu powiedzieć:
std::vector<ValueType> vec(a, a + n);
...zakładając, że a
jest twoją tablicą, a n
jest liczbą elementów, które zawiera. W przeciwnym razie, std::copy()
w / resize()
załatwi sprawę.
Trzymałbym się z dala od memcpy()
, chyba że możesz być pewien, że wartości są zwykłymi typami danych (POD).
Warto również zauważyć, że żadna z nich nie unika pętli for-tylko pytanie, czy musisz ją zobaczyć w swoim kodzie albo i nie. O (n) wydajność runtime jest nieunikniona przy kopiowaniu wartości.
Na koniec zauważ, że tablice w stylu C są doskonale poprawnymi kontenerami dla większości algorytmów STL-wskaźnik raw jest równoważny begin()
, a (ptr + n
) jest równoważny end()
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-10 14:54:50
Było tu wiele odpowiedzi i prawie wszystkie z nich wykonają zadanie.
Jest jednak jakaś myląca Rada!
Oto opcje:
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());
}
Aby wyciąć długą historię, metoda 4, używając vector:: insert, jest najlepsza dla scenariusza bsruth.
Oto kilka krwawych szczegółów:
Metoda 1 jest prawdopodobnie najłatwiejsza do zrozumienia. Wystarczy skopiować każdy element z tablicy i wcisnąć go z tyłu wektora. Niestety, powoli. Ponieważ istnieje pętla (implikowana z funkcją kopiowania), każdy element musi być traktowany indywidualnie; nie można poprawić wydajności w oparciu o fakt, że wiemy, że tablica i wektory są sąsiadującymi blokami.
Metoda 2 jest sugerowaną poprawą wydajności do metody 1; wystarczy wstępnie zarezerwować rozmiar tablicy przed jej dodaniem. Dla dużych tablic ten Może pomóc. Jednak najlepszą radą tutaj jest nigdy nie używać rezerwy, chyba że profilowanie sugeruje możesz być w stanie uzyskać poprawę (lub musisz upewnić się, że Iteratory nie zostaną unieważnione). Bjarne zgadza się . Nawiasem mówiąc, odkryłem, że metoda ta wykonywała najwolniej przez większość czasu, chociaż staram się wyczerpująco wyjaśnić, dlaczego była regularnie znacząco wolniejsza niż metoda 1...
Metoda 3 jest starym rozwiązaniem-rzuć trochę C w problem! Działa dobrze i szybko dla typów POD. W tym przypadku resize jest wymagane do wywołania, ponieważ memcpy działa poza granicami wektora i nie ma sposobu, aby powiedzieć wektorowi, że jego rozmiar się zmienił. Poza tym, że jest brzydkim rozwiązaniem (kopiowanie bajtów!) pamiętaj, że to może być używane tylko dla typów POD . Nigdy nie użyłbym tego rozwiązania.
metoda 4 jest najlepszym sposobem. Jego znaczenie jest jasne, jest (zazwyczaj) najszybsze i działa dla dowolnych obiektów. Nie ma minusów stosowania tej metody do tego podanie.
metoda 5 jest modyfikacją metody 4-skopiowanie tablicy do wektora, a następnie jej dołączenie. Dobra opcja-generalnie szybka i przejrzysta.
Wiesz wreszcie, że możesz używać wektorów zamiast tablic, prawda? Nawet jeśli funkcja oczekuje tablic w stylu c, można użyć wektorów:vector<char> v(50); // Ensure there's enough space
strcpy(&v[0], "prefer vectors to c arrays");
Mam nadzieję, że to komuś pomoże!Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-11-04 11:42:17
Jeśli wszystko, co robisz, to zastępujesz istniejące dane, możesz to zrobić
std::vector<int> data; // evil global :)
void CopyData(int *newData, size_t count)
{
data.assign(newData, newData + count);
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-11-03 17:39:26
Std:: copy jest tym, czego szukasz.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-11-03 17:07:34
Ponieważ mogę edytować tylko własną odpowiedź, zrobię odpowiedź złożoną z innych odpowiedzi na moje pytanie. Dziękuję wszystkim, którzy odpowiedzieli.
Używając std:: copy, to nadal działa w tle, ale nie musisz wpisywać kodu.
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;
}
Używając zwykłej memcpy . Jest to prawdopodobnie najlepiej używane dla podstawowych typów danych (tj. int), ale nie dla bardziej złożonych tablic struktur lub klas.
vector<int> x(size);
memcpy(&x[0], source, size*sizeof(int));
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-11-03 20:28:38
Unikaj memcpy, mówię. Nie ma powodu, aby zadzierać z operacjami wskaźnikowymi, chyba że naprawdę musisz. Ponadto będzie działać tylko dla typów POD (takich jak int), ale zawiedzie, jeśli masz do czynienia z typami, które wymagają budowy.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-11-03 17:17:55
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 :-)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-01 15:01:28
Oprócz metod przedstawionych powyżej, musisz upewnić się, że używasz std:: Vector.reserve (), std:: Vector.resize (), lub skonstruować wektor do rozmiaru, aby upewnić się, że wektor ma wystarczającą ilość elementów do przechowywania danych. jeśli nie, zepsujesz pamięć. Dotyczy to std:: copy() lub memcpy ().
Jest to powód użycia wektora.push_back (), nie można pisać poza końcem wektora.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-11-03 17:29:02
Kolejna odpowiedź, ponieważ osoba powiedziała "Nie wiem, ile razy moja funkcja będzie wywoływana", możesz użyć metody Vector insert w taki sposób, aby dołączyć tablice wartości do końca wektora:
vector<int> x;
void AddValues(int* values, size_t size)
{
x.insert(x.end(), values, values+size);
}
Podoba mi się ten sposób, ponieważ implementacja wektora powinna być w stanie zoptymalizować pod kątem najlepszego sposobu wstawiania wartości na podstawie typu iteratora i samego typu. Trochę odpowiadasz na temat implementacji stl.
Jeśli chcesz zagwarantować najszybsza prędkość i wiesz, że Twój typ jest typu POD, to polecam metodę resize w odpowiedzi Thomasa:
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));
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-11-03 18:56:15
Zakładając, że wiesz jak duży jest element w wektorze:
std::vector<int> myArray;
myArray.resize (item_count, 0);
memcpy (&myArray.front(), source, item_count * sizeof(int));
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-11-03 17:09:15