Mam tablicę wartości, które są przekazywane do mojej funkcji z innej części programu, którą muszę przechowywać do późniejszego przetworzenia. Ponieważ nie wiem, ile razy moja funkcja zostanie wywołana, zanim nadejdzie czas na przetworzenie danych, potrzebuję dynamicznej struktury pamięci, więc wybrałem plik std::vector
. Nie chcę wykonywać standardowej pętli dla push_back
wszystkich wartości z osobna, byłoby miło, gdybym mógł to wszystko skopiować za pomocą czegoś podobnego do memcpy
.
vec.assign(a, a+n)
, który byłby bardziej kompaktowy niż Kopiuj i rozmiaru.Było tu wiele odpowiedzi i prawie wszystkie z nich wykonają swoją pracę.
Jest jednak kilka mylących rad!
Oto opcje:
Krótko mówiąc, metoda 4, wykorzystująca vector :: insert, jest najlepsza w scenariuszu bsruth.
Oto kilka krwawych szczegółów:
Metoda 1 jest prawdopodobnie najłatwiejsza do zrozumienia. Po prostu skopiuj każdy element z tablicy i wepchnij go z tyłu wektora. Niestety, jest powolny. Ponieważ istnieje pętla (implikowana z funkcją kopiowania), każdy element musi być traktowany indywidualnie; nie można poprawić wydajności na podstawie faktu, że wiemy, że tablica i wektory są ciągłymi blokami.
Metoda 2 to sugerowana poprawa wydajności w stosunku do Metody 1; po prostu zarezerwuj rozmiar tablicy przed jej dodaniem. W przypadku dużych tablic może to pomóc. Jednak najlepszą radą tutaj jest, aby nigdy nie używać rezerwy, chyba że profilowanie sugeruje, że możesz być w stanie uzyskać poprawę (lub musisz upewnić się, że twoje iteratory nie zostaną unieważnione). Bjarne zgadza się . Nawiasem mówiąc, zauważyłem, że ta metoda działała najwolniej przez większość czasu, chociaż staram się kompleksowo wyjaśnić, dlaczego regularnie była znacznie wolniejsza niż metoda 1 ...
Metoda 3 to stara szkoła - rzuć trochę C na problem! Działa dobrze i szybko w przypadku typów POD. W tym przypadku konieczne jest wywołanie resize, ponieważ memcpy działa poza granicami wektora i nie ma sposobu, aby powiedzieć wektorowi, że jego rozmiar się zmienił. Oprócz tego, że jest to brzydkie rozwiązanie (kopiowanie bajtów!), Pamiętaj, że może to być używane tylko dla typów POD . Nigdy bym nie skorzystał z tego rozwiązania.
Metoda 4 to najlepszy sposób. To znaczy jest jasne, jest (zwykle) najszybsze i działa na dowolnych obiektach. Nie ma wad korzystania z tej metody w tej aplikacji.
Metoda 5 to ulepszenie metody 4 - skopiuj tablicę do wektora, a następnie dołącz ją. Dobra opcja - ogólnie szybka i przejrzysta.
Wreszcie wiesz, że możesz używać wektorów zamiast tablic, prawda? Nawet jeśli funkcja oczekuje tablic w stylu c, możesz użyć wektorów:
Mam nadzieję, że to pomoże komuś tam!
źródło
&expr
nie oceniaexpr
, a jedynie oblicza jego adres. Wskaźnik znajdujący się jeden za ostatnim elementem jest również całkowicie poprawny.dataVec.insert(dataVec.end(), dataArray, dataArray + dataArraySize);
- wydaje mi się dużo jaśniejszy. Nie można też niczego uzyskać z metody 5, tylko wygląda dość nieefektywnie - chyba że kompilator jest w stanie ponownie zoptymalizować wektor.Jeśli wszystko, co robisz, to zastępowanie istniejących danych, możesz to zrobić
źródło
std :: copy jest tym, czego szukasz.
źródło
Ponieważ mogę edytować tylko własną odpowiedź, zamierzam utworzyć złożoną odpowiedź na podstawie innych odpowiedzi na moje pytanie. Dziękuję wszystkim, którzy odpowiedzieli.
Używając std :: copy , to nadal iteruje w tle, ale nie musisz wpisywać kodu.
Używanie zwykłego 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.
źródło
unikaj mempy, mówię. Nie ma powodu, by bawić się operacjami wskaźnika, 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ą konstrukcji.
źródło
źródło
myints
?Jeszcze inna odpowiedź, ponieważ osoba ta powiedziała „Nie wiem, ile razy moja funkcja zostanie wywołana”, możesz użyć metody wstawiania wektorów w taki sposób, aby dołączyć tablice wartości na końcu wektora:
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. W pewnym stopniu odpowiadasz na temat implementacji STL.
Jeśli chcesz zagwarantować największą prędkość i wiesz, że Twój typ to POD, to polecam metodę zmiany rozmiaru w odpowiedzi Thomasa:
źródło
Oprócz metod przedstawionych powyżej, musisz upewnić się, że używasz std :: Vector.reserve (), std :: Vector.resize () lub skonstruujesz wektor do rozmiaru, aby upewnić się, że wektor ma wystarczającą liczbę elementów w do przechowywania danych. jeśli nie, zepsujesz pamięć. Dotyczy to zarówno std :: copy (), jak i memcpy ().
To jest powód używania vector.push_back (), nie możesz pisać poza końcem wektora.
źródło
Zakładając, że wiesz, jak duży jest element w wektorze:
http://www.cppreference.com/wiki/stl/vector/start
źródło