• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

vector jako argument funkcji

Object Storage Arubacloud
+1 głos
619 wizyt
pytanie zadane 24 stycznia 2021 w C i C++ przez hicodyn Początkujący (420 p.)

Mam funkcję, która jako parametr ma przyjąć vector<punkt> (punkt to struktura stworzona przeze mnie). W trakcie działania funkcja przepisuje jeden element z tego vectora do innego, który zwraca. Jak zrobić, żeby funkcja mogła zmodyfikować zawartość vectora, który jest przekazany jako parametr funkcji? Tutaj jest kod:

std::vector<punkt> zapisCentroidow(daneWejsciowe przelaczniki,std::vector<punkt> vectorPunktow)
{
    std::vector<punkt> vectorCentroidow;
    for (int i = 0; i < przelaczniki.k; i++)
    {
        vectorCentroidow.push_back(vectorPunktow[i]);
        vectorPunktow.erase(vectorPunktow.begin(),vectorPunktow.begin()+1);
    }

    return vectorCentroidow;
}

 

1 odpowiedź

+2 głosów
odpowiedź 24 stycznia 2021 przez NewEraOfPeace Gaduła (4,790 p.)
wybrane 25 stycznia 2021 przez hicodyn
 
Najlepsza
Przekaż vector poprzez referencje.
Kilka rzeczy:
1. Czy masz zawsze 100% pewności, że przelaczniki.k będzie mniejsze/równe ilości elementów w vectorze? Jeśli nie, to polecam wykonać jakieś sprawdzenia
2. Do zwykłej iteracji używaj size_t, zamiast int, a w tym przypadku nawet ranged for
3. Wygląda mi na to, że tutaj w zasadzie wystarczy Ci move
komentarz 24 stycznia 2021 przez hicodyn Początkujący (420 p.)
a w jaki sposób działa move?
1
komentarz 25 stycznia 2021 przez NewEraOfPeace Gaduła (4,790 p.)

Nie wchodząc w szczegóły - jeśli masz coś dużego, czego kopiowanie zajęłoby trochę czasu i wiesz, że za niedługo nie będziesz tego potrzebować, ale jednak będziesz potrzebować tych danych gdzie indziej, bez potrzeby kopiowania. Move robi to co Ty chcesz - (w tym przypadku) przenosi dane z jednego vectora do drugiego + zeruje tamten vector. Zamiast tej funkcji w jednym miejscu mógłbyś po prostu napisać
 

std::vector<punkt> nazwa = std::move(nazwa_tamtego_vectora);


ofc - correct me if Im wrong

komentarz 25 stycznia 2021 przez tkz Nałogowiec (42,000 p.)

@NewEraOfPeace, O ile faktycznie "vectorPunktow" jest dalej niepotrzebny. Jeżeli jest częścią logiki, kontenerem, który służy jako wsad do filtrowania, nie ma sensu używać semantyki przenoszenia. Niech przekazuje jako referencję, a RVO zajmie się resztą.

2. Do zwykłej iteracji używaj size_t, zamiast int, a w tym przypadku nawet ranged for

O ile "przelaczniki.k" jest również typu size_t, inaczej kompilator będzie wspominał o niezgodności typów. 

Pytanie do autora. Kolejność w przekazywanym wektorze ma znaczenie? 

komentarz 25 stycznia 2021 przez NewEraOfPeace Gaduła (4,790 p.)

@NewEraOfPeace, O ile faktycznie "vectorPunktow" jest dalej niepotrzebny. Jeżeli jest częścią logiki, kontenerem, który służy jako wsad do filtrowania, nie ma sensu używać semantyki przenoszenia. Niech przekazuje jako referencję, a RVO zajmie się resztą.

Ta funkcja jest cholernie wolna (zakładając, że danych jest dużo,  u mnie dla 1024*100*8B działała ok. 4500ms, z przekazywaniem przez referencję i resizem) i to nie z uwagi na kopię. Skoro zawartość vectora i tak zostaje usunięta, nie widzę problemu, w robieniu move'a (który u mnie na maszynie nie zajmuje praktycznie żadnego czasu, dosłownie, chrono mierzy mi 0ns).

 

O ile "przelaczniki.k" jest również typu size_t, inaczej kompilator będzie wspominał o niezgodności typów. 

Owszem, jednak w tym kontekście zakładam, że jest to member przechowujący jakiś rozmiar, a więc, że jest typu size_t. 

komentarz 25 stycznia 2021 przez hicodyn Początkujący (420 p.)

@tkz, nie, kolejność w przekazywanym vectorze nie ma znaczenia

komentarz 25 stycznia 2021 przez hicodyn Początkujący (420 p.)
przelaczniki.k jest zwyklym int-em, który informuje ile punktów z vectorPunktow ma byc przeniesionych do vectorCentroidow
1
komentarz 25 stycznia 2021 przez NewEraOfPeace Gaduła (4,790 p.)
Jeśli nie używasz tej zmiennej do żadnych obliczeń później (gdzie potencjalnie mógłbyś dostać ujemny wynik), to zamieniłbym to z int na size_t, w przeciwnym razie wszystko dobrze.
komentarz 25 stycznia 2021 przez tkz Nałogowiec (42,000 p.)

@NewEraOfPeace,

@NewEraOfPeace, O ile faktycznie "vectorPunktow" jest dalej niepotrzebny. Jeżeli jest częścią logiki, kontenerem, który służy jako wsad do filtrowania, nie ma sensu używać semantyki przenoszenia. Niech przekazuje jako referencję, a RVO zajmie się resztą.

Ta funkcja jest cholernie wolna (zakładając, że danych jest dużo,  u mnie dla 1024*100*8B działała ok. 4500ms, z przekazywaniem przez referencję i resizem) i to nie z uwagi na kopię. Skoro zawartość vectora i tak zostaje usunięta, nie widzę problemu, w robieniu move'a (który u mnie na maszynie nie zajmuje praktycznie żadnego czasu, dosłownie, chrono mierzy mi 0ns).

Mógłbyś udostępnić kod, który mierzyłeś? Problemem jest usuwanie, które jest liniowe. 

template <typename T>
void quick_remove_at(std::vector<T>& v, 
                     typename std::vector<T>::iterator it)
{
    if (it != std::end(v)) {
        *it = std::move(v.back());
        v.pop_back();
    }
}

Usuwanie, które jest stałe, ale zmienia kolejność w wektorze. Coś za coś. 

komentarz 25 stycznia 2021 przez NewEraOfPeace Gaduła (4,790 p.)
To co Ty robisz to po prostu std::move (ten drugi, z <algorithm>), który w zasadzie zostawia nas z bardzo podobnym stanem, co zwyczajny std::move (ten z <utility>). Kod, który mierzyłem, to ten sam kod, który udostępnił OP. Testowałem tylko różne jego wersje - z przekazywaniem przez referencję, z resize do rozmiaru vectora z parametru, oba na raz.
komentarz 25 stycznia 2021 przez tkz Nałogowiec (42,000 p.)
Wiem co robię. Kwestia kosztu. Standardowy erase jest O(n), gdzie podany przeze mnie jest w O(1). Mierzenie kodu autora sprowadza się do usuwania, które jest najbardziej czasochłonne. Kopiowanie to minimalny koszt w porównaniu z pętlą.
komentarz 25 stycznia 2021 przez NewEraOfPeace Gaduła (4,790 p.)
No tak, bo usuwamy z przodu, a nie z tyłu, ale tak czy siak nie widzę sensu pisać osobnej funkcji tego typu, skoro std::move zrobi to za nas i to jeszcze szybciej.
komentarz 25 stycznia 2021 przez tkz Nałogowiec (42,000 p.)
Ale co zrobi? Usunie? Przeniesie własność? Nie wiem do końca do czego się odnosisz. Kod by dużo rozjaśnił.  Bez testów wydajnościowych, trudno mi powiedzieć co będzie lepsze, czytaj szybsze.
komentarz 25 stycznia 2021 przez NewEraOfPeace Gaduła (4,790 p.)
Przenosi własność, mam na myśli move jako cast do r-val reference.

Podobne pytania

0 głosów
1 odpowiedź 856 wizyt
pytanie zadane 8 kwietnia 2018 w C i C++ przez giedymin33 Początkujący (290 p.)
+1 głos
0 odpowiedzi 456 wizyt
pytanie zadane 2 czerwca 2021 w C i C++ przez Mavimix Dyskutant (8,390 p.)
0 głosów
1 odpowiedź 312 wizyt
pytanie zadane 15 maja 2020 w C i C++ przez Majster6918 Gaduła (4,030 p.)

92,631 zapytań

141,498 odpowiedzi

319,869 komentarzy

62,011 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...