Jak najszybciej stworzyć vector własnych klas

0

Witam,
Mam pewną klasę. Kontener jaki wybrałem do przechowywania jej obiektów to wektor, bo w czasie działania programu ilość elementów będzie się często zmieniać. Problem jaki mam to jaką technikę wybrać by czas stworzenia/zainicjalizowania wektora po starcie programu był jak najszybszy?
Na razie mam tak:

vector<Gracz> gracze;	gracze.push_back(Gracz(0,"Józef","Anielewski",lewy,Date(22,March,1993),12,13,18,8,5,4,4,16,6,18,20,15,18,brak));
...
//około 22 push_backów

W grze by było przy starcie około tysiąca push_backów. Moja klasa ma konstruktor zdefiniowany przeze mnie => stąd formuła Gracz(0,"Józef",....)

Myślałem by zrobić też tak:

vector<Gracz> gracze(22);
gracze.at(0) = Gracz(0,"Józef","Anielewski",lewy,Date(22,March,1993),12,13,18,8,5,4,4,16,6,18,20,15,18,brak);

ale tu wyciek pamięci będę miał bo powstaną 22 konstruktory domyślne Gracz() które potem nie zostaną zabite.

Najlepiej by było nie brać wektora tylko dać:

Gracz gracze[22] = { Gracz(0,"Józef","Anielewski",lewy,Date(22,March,1993),12,13,18,8,5,4,4,16,6,18,20,15,18,brak),
                             Gracz(1,"Adam","Anielewski",lewy,Date(22,March,1993),12,13,18,8,5,4,4,16,6,18,20,15,18,brak)
itd.itp.  };

i czas tego jest szybszy niż wypełniania wektora.
Ale wektor ma dużo metod, które mi się potem przydadzą i stąd chciałbym mieć wektor. Ma ktoś jakiś pomysł?

0

Zamiast obiektów przechowuj wskaźniki do nich (ominiesz niepotrzebne kopiowanie)

0

Naprawdę zrobiłeś konstruktor na 19 argumentów? Wróć do podstaw zamiast gry pisać, to szczera rada.

0

Pętla.

string imie, nazwisko;
vector<Gracz> gracze;
for(int i = 0; i < 22; i++)
{
    cout << "Podaj imie gracza: ";
        cin >> imie;
    cout << "Podaj nazwisko gracza: ";
        cin >> nazwisko;
    gracze.push_back(Gracz(i, imie, nazwisko,lewy,Date(22,March,1993),12,13,18,8,5,4,4,16,6,18,20,15,18,brak));
}

Jeżeli chcesz na sztywno wprowadzic imiona z programu, to stworz tablice imiona[22] i nazwiska[22] uzupełnij je i potem
<cpp>gracze.push_back(Gracz(i, imie[i], nazwiska[i],lewy,Date(22,March,1993),12,13,18,8,5,4,4,16,6,18,20,15,18,brak));<cpp>

poza tym zrób tak jak mówi @bzyku_guzio, bo wektory pobierają kopie obiektów które wprowadzasz, a to drugie tyle czasu.

0

ale tu wyciek pamięci będę miał bo powstaną 22 konstruktory domyślne Gracz() które potem nie zostaną zabite.

to nie ma znaczenia, bo nadpisujesz ten sam obszar pamięci. tak że wycieku nie będzie. co innego, jeśli konstruktor domyślny klasy Gracz coś alokuje dynamicznie - ale i tak przed nadpisaniem obiektu wykona się destruktor, a w nim powinieneś zwalniać tę pamięć.

ale prawda że to wszystko nadmiarowe operacje (zwłaszcza że odpalany będzie konstruktor ORAZ destruktor dla każdego elementu)

0

Dodatkowo jeszcze ruszy do akcji konstruktor kopiujący.
Tak jak powiedział stonoga, taki konstruktor to nawet w koszmarach się nie śni. Ogólnie staraj się trzymać zasady, że metoda nie powinna mieć więcej jak 3 argumenty, potem staje się to mocno nieczytelne.

0

Polecałbym wektor wskaźników -- odpada kopiowanie obiektów; może to być na przykład smart_ptr. Ponadto metoda reserve() wektora mogłaby pomóc, ale w twoim przypadku wąskim gardłem jest właśnie kopiowanie.

I tak jak przedmówcy: konstruktor jest fatalny. Przy takiej liczbie parametrów pomyśl o redesignie albo chociaż o jakiejś fabryce.

0

Nie mogę się zgodzić ze stwierdzeniami, że konstruktor jest fatalny. Własnie nie jest fatalny bo parametry obiektu trzymam w jednej linii kodu. Mam:
Gracz(0,"Józef","Anielewski",lewy,Date(22,March,1993),12,13,18,8,5,4,4,16,6,18,20,15,18,brak) i wszystko wiem o obiekcie. Wiem na pamięć który parametr co oznacza. Poza tym jak ktoś pisze, że jest fatalny to nie może napisac że jest fatalny, tylko w zamian coś innego musi zaproponować, bo tak to to mało przekonujący argument:)

0
byku_guzio napisał(a)

Zamiast obiektów przechowuj wskaźniki do nich (ominiesz niepotrzebne kopiowanie)

Czyli dać:

vector<* Gracz> gracze;        
Gracz temp;
gracze.push_back(&(temp=Gracz(0,"Józef","Anielewski",lewy,Date(22,March,1993),12,13,18,8,5,4,4,16,6,18,20,15,18,brak)));
...
//około 22 push_backów
0

Nie nie nie, broń Cię panie boże!

@kwestia konstruktora: teraz znasz na pamięć kolejność argumentów, ale jak wrócisz do kodu po tygodniu przerwy to już będzie pozamiatane. Dodatkowo taki konstruktor jest po prostu całkowicie nieczytelny. Zdecydowanie lepiej by było stworzyć obiekt, i po kolei ustawiać odpowiednie pola. Polecam lekturę książki "Czysty kod" Robert C. Martin

@pytanie: brakuje Ci wiedzy na temat wskaźników i czasu życia obiektów(nie uraź się, ale skoro piszesz grę to dobrze by było to wiedzieć)

vector<Gracz*> gracze;
Gracz *tmp;
tmp = new Gracz(...);
gracze.puszh_back(tmp);

ewentualnie krócej:

vector<Gracz*> gracze;
gracze.push_back(new Gracz(...));

na końcu nie możesz zapomnieć o zwolnieniu pamięci.

0
tomek k. napisał(a)

Wiem na pamięć który parametr co oznacza

Wiesz na pamięć a argumenty to na palcach liczysz? Przede wszystkim pogrupuj spokrewnione dane w klasy, klasa powinna realizować tylko jeden cel, u Ciebie wygląda na to, że pierze, sprząta, dusi kota i gotuje, przeprojektuj. Jeżeli faktycznie takiego ogromu informacji dla kolejnych elementów potrzebujesz to zainteresuj się http://en.wikipedia.org/wiki/Builder_pattern

0

Przeładuj operator. Zrób coś na taki wzór

class Gracz
{
public:
	char imie[20];
	char nazwisko[20];
};

istream& operator>>(istream& strumien, Gracz& gracz)
{
     cout << "Podaj imie gracza: ";
     strumien >> gracz.imie;
     cout << "Podaj nazwisko gracza: ";
     strumien >> gracz.nazwisko;
     //...
	 return strumien;
}
0

a może boost::list_of?

0

I wciągać całego boosta żeby zaoszczędzić pisania (nawet i nie, bo kopiowania) 10 - 15 znaków, bez sensu

0
byku_guzio napisał(a)

Nie nie nie, broń Cię panie boże!

@kwestia konstruktora: teraz znasz na pamięć kolejność argumentów, ale jak wrócisz do kodu po tygodniu przerwy to już będzie pozamiatane. Dodatkowo taki konstruktor jest po prostu całkowicie nieczytelny. Zdecydowanie lepiej by było stworzyć obiekt, i po kolei ustawiać odpowiednie pola. Polecam lekturę książki "Czysty kod" Robert C. Martin

@pytanie: brakuje Ci wiedzy na temat wskaźników i czasu życia obiektów(nie uraź się, ale skoro piszesz grę to dobrze by było to wiedzieć)

vector<Gracz*> gracze;
Gracz *tmp;
tmp = new Gracz(...);
gracze.puszh_back(tmp);

ewentualnie krócej:

vector<Gracz*> gracze;
gracze.push_back(new Gracz(...));

na końcu nie możesz zapomnieć o zwolnieniu pamięci.

@kwestia
Ale chodzi o skupienie wszystkich parametrów zwięźle w jednym miejscu.
@pytanie
Twój kod jest beznadziejny, bo użytkownik o wiele dłużej będzie czekał na wykonanie kodu (operator new) niż jak się tworzy statycznie obiekt.

0

To jak Ty chcesz stworzyć wszystkie obiekty statycznie i wrzucić do wektora? Jeżeli stworzysz statycznie to do wektora możesz wrzucać wskaźniki, ale wtedy nie daj bóg wyjdziesz z zasięgu obowiązywania tych graczy i pozamiatane - wskaźniki będą pokazywać w kosmos.
Jeżeli będziesz przechowywać jako obiekty to dojdzie Ci narzut czasu na kopiowanie ich do wektora.

Tworząc te obiekty na stercie nie masz tych problemów i wcale to nie jest tak dużo wolniejsze(pewnie nawet nie zauważysz różnicy) - zawsze możesz napisać placement new, który zoptymalizuje dla Ciebie alokacje pamięci.

0
tomek k. napisał(a)

Nie mogę się zgodzić ze stwierdzeniami, że konstruktor jest fatalny. Własnie nie jest fatalny bo parametry obiektu trzymam w jednej linii kodu. Mam:
Gracz(0,"Józef","Anielewski",lewy,Date(22,March,1993),12,13,18,8,5,4,4,16,6,18,20,15,18,brak) i wszystko wiem o obiekcie. Wiem na pamięć który parametr co oznacza. Poza tym jak ktoś pisze, że jest fatalny to nie może napisac że jest fatalny, tylko w zamian coś innego musi zaproponować, bo tak to to mało przekonujący argument:)

Jeśli dasz sobie uciąć głowę i jajca,że tego kodu nikt nigdy poza tobą nie będzie oglądał,to i owszem,możesz wiedzieć co jest co i może sobie być tak jak jest z tymi 19 parametrami.Ja widząc taką linijkę kodu mam odruch który daje się opisać "?!Aale o co k*wa chodzi?!(tak zgaduję,że piszesz coś ala manager piłkarski i to są parametry zawodnika)
No właśnie,oglądanie kodu-na pewno aby nie będziesz kiedyś chciał pokazać w CV podczas szukania pracy,że taki program napisałeś?I po naszych komentarzach na forum nietrudno Bracie zgadnąć,co sobie o Tobie pomyśli ewentualny pracodawca.

0
tomek k. napisał(a)

Nie mogę się zgodzić ze stwierdzeniami, że konstruktor jest fatalny. Własnie nie jest fatalny bo parametry obiektu trzymam w jednej linii kodu. Mam:
Gracz(0,"Józef","Anielewski",lewy,Date(22,March,1993),12,13,18,8,5,4,4,16,6,18,20,15,18,brak) i wszystko wiem o obiekcie. Wiem na pamięć który parametr co oznacza. Poza tym jak ktoś pisze, że jest fatalny to nie może napisac że jest fatalny, tylko w zamian coś innego musi zaproponować, bo tak to to mało przekonujący argument:)

Ten konstruktor w naszym świecie, w języku C++, jest fatalny.
We wszechświatach równoległych, w których parametry w C++ mogą być nazwane, nie byłby taki zły ;-)

Taka konstrukcja jak Twoja wyłoży się przy próbie wywołania konstruktora z domyślną wartością parametru nr 3 - żeby to zrobić musiałbyś resztę parametrów (4,5...n) ustawić na domyślne wartości - a nie zawsze się da albo nie zawsze to jest logiczne.

Czyli zamiast tego co mogłoby być:
Gracz(parametr_A = 0, imie = "Józef", nazwisko = "Anielewski", pozycja = lewy, costam = 5)

trzeba pisać:

std::auto_ptr<Gracz> nowyGracz(new Gracz);
nowyGracz->parametr_A = 0
nowyGracz->imie = "Jozef"
nowyGracz->nazwisko = "Anieleski"
nowyGracz->pozycja = lewy
nowyGracz->costam = 5

Inny sposób:
http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.20

1 użytkowników online, w tym zalogowanych: 0, gości: 1