Zdravím všechny,
vytvořil sem si jednoduchou třídu Oblasti, která má jednu
privátní proměnnou. Dvojrozměrné pole vector obsahující
dvojice : ukazatel na objekt Node a boolovskou proměnnou.
Počet řádků i sloupců toho pole je předem známý, je určen makry
PPRV_RADKY a PPRV_SLOUPCE. ( Proto bych chtěl předem vymezit
celý prostor pole a ne jednotlivě přidávat řádky ) Toto pole bych
chtěl inicializovat (alokovat prostor) v konstruktoru třídy. Průběh
Inicializace si představuji následovně. Nejprve by se měli naalokovat řádky.
Takze nejak takhle pprv(PPRV_RADKY) a potom ve for cyklu by se
alokovali sloupce. for(int i = 0; (int) i < pprv.size(); i++)
pprv[i] = vector < pair <Node *, bool> >(PPRV_SLOUPCE, pair<NULL, true>);
Přičemž hodnota každé dvojice pole by byla NULL a true.
Snažil sem se to vygooglit ale nenašel sem nic použitelného. Buď
sem hledal špatně a nebo to nejde. Budu rád za jakýkoliv příspěvek,
případně pokud by to někdo věděl a mohl uvést příklad bylo by to
uplně super !
Předem díky všem.
#include <vector>
#define PPRV_RADKY 20
#define PPRV_SLOUPCE 6
using std::vector;
using std::pair;
class Oblasti
{
vector < vector < pair <Node *, bool> > > pprv;
public:
Oblasti() {
// !!!sem doplnit kod inicializace pole pprv !!!
}
~Oblasti();
};
Fórum › C / C++
Inicializace dvojrozmerneho pole v konstruktoru tridy
pokud dopredu vis rozmery pole, pak je dle me lepsi ho alokovat staticky, a ne jako vector. tedy jednoduse pair<Node*,bool> pole [H][W];
inicializace v konstruktoru je primocara. pokud presto chces vector, pak si alokaci dostatecneho poctu polozek zaridis volanim reserve, popr. resize (rozdil je v tom, ze reserve pouze alokuje misto, a vector se stale bude tvarit jako prazdny: tedy nemuzes indexovat vsechny polozky, a prvky pridavas pomoci push_back; zatimco resize primo zmeni udaj o velikosti vectoru, a muzes vsechny polozky rovnou indexovat).
tedy neco jako:
pole.resize( H );
for(i=0;i<H:i++)
pole[i].resize(W); /* nevyhoda tohoto reseni je, ze te stoji docela dost casu (obzvlaste pokud takovychto trid bude vice) */
jak je to s bezparametrickym konstruktorem pairu nevim, radsi si od pairu vyded vlastni tridu ktere napis bezparametricky konstruktor nastavujici zadane hodnoty.
No ono takhle, abych to uvedl na správnou míru. Předem je známý
jen počet řádků toho pole, ale počet sloupců ne, a navíc počet těch
položek na řádku se bude v průběhu vykonávání programu také měnit.
Proto potřebuji mít to pole nestatické. Jinak na inicializovanych hodnotach
v tom poli tak uplně nezáleží. Neni podstatne jestli tam bude NULL, a true.
To se bude upravovat později. Takže pokud sem dobře pochopil to s tím
reserve bude to v konstruktoru vypadat asi takhle...
pprv.reserve(PPRV_RADKY);
vector< pair<Node *, bool > > vp;
for(vector<vector <pair <Node *, bool> > >::iterator h = pprv.begin(); h < pprv.end(); h++)
{
h.push_back(vp);
h.reserve(NEJAKE_PREDEM_NEZNAME_CISLO);
}
Pardon oprava. Jde mi jen o prostor ne prvky, ty si tam vlozim pozdeji. Chci jen dost mista, aby nedoslo
k prekopirovavani z nedostatku vymezeneho mista...
pprv.reserve(PPRV_RADKY);
for(vector<vector <pair <Node *, bool> > >::iterator h = pprv.begin(); h < pprv.end(); h++)
{
h->reserve(NEJAKE_PREDEM_NEZNAME_CISLO);
}
To Laďas : jasne to je ta myslenka. ale jeste bych dodal, ze ac jsou iteratory sexy, tak nejsou uplne rychle. v takove situaci bych se vubec nestydel pouzit klasicky pruchod po jedne... vznikly pocet instrukci je odhadem trikrat mensi nez pri iteratoru
ale v obou pripdach volej resize a ne reserve (tedy alespon v situaci pprv.resize; u prvku tohoto vectoru uz to zalezi na pozdejsi situaci). pokud totiz zavolas reserve na prazdny vector, tak zustane prazdny, jen bude zabirat vice pameti: tedy jeho size bude rovna nule, stejne tak end == begin, a pristup k nekteremu prvku vectoru vyvola chybu. pokud zavolas resize, primo ovlivnis zminene atributy.
to tmi To tmi : Dik chlape pomohl jsi mi :smile2: Jasne to sem pochopil. Na sexy iteratory :smile5: si dam pozor, budu to ale muset jeste overit. Prislo mi prave efektivnejsi pouzit iteratory, protoze pri pouziti for cyklu kde bych to pole indexoval dochazi k vypoctu adresy daneho prvku v poli. Coz mi prislo neefektivni...
To Laďas : a myslis ze pri iteratorech se to nedeje?:) adresu kam zapisovat musis zjistovat vzdy, a pokud indexujes celym cislem da se to zvladnout jedinou instrukci, konkretne lea. jak presne to delaji iteratory nevim, ale rychleji z principu ani nemuzou (nehlede na to, ze pokud tech radku mas mas malo a je dopredu znam jejich pocet, chytry kompilator to u klasickeho pruchodu zoptimalizuje tak ze se vubec nepouzije cyklus)
To tmi : Nez bych to tu rozepisoval radeji uvedu priklad.
#define ROZMER
int pole[10][10];
// neefektivne
for(int i=0;i< ROZMER: i++)
for(int j=0;j< ROZMER: j++)
pole[i][j]= 0;
//efektivne
int rozsah = ROZMER * ROZMER;
int *pint = &pole[0][0];
for(int i=0; i < rozsah: i++)
{
*pint = 0;
++pint;
}
Rekl bych ze ten druhy for cyklus bude efektivnejsi protoze se tam neustale neprepocitava ta adresa jako u toho prvniho, pouze inkrementuje. POdobne sem myslel ze je to i s iteratory.
To Laďas : pravda je ze bez zapnute optimalizace bude ten druhy cyklus o neco lepsi, kompilator (gcc) ten vnoreny cyklus prelozil docela hloupe - zatimco v druhem cyklu primocare projede pole, v prvnim adresu vypocitava docela podivne s pouzitim tri registru... ale v praxi by se to dle me moc neprojevilo (snad jen kdyz by to pole bylo hodne velike, v takovem pripade by to ale stejne bylo prebito poctem cache misu), obzvlaste kdyz by se kompilovalo se zapnutou optimalizaci. ona totiz slozitejsi adresova reference nestoji zadnou instrukci navic,
takze jedine co vadi je tech par aritmetickych operaci, ktere jsou ale velice rychle.
kazdopadne je ale pouziti iteratoru je vyrazne pomalejsi nez jakykoli primocary pristup... vyzkousej a uvidis:)
To tmi : Ja sem to pak jeste zkousel v kombinaci ukazatel na pocatek pole + nejaky offset a bylo to jeste rychlejsi nez obe vyse zminovane moznosti. Mas urcite pravdu, aritmeticke operace byvaji co do poctu taktu provedeny mnohem rychleji nez samotna adresace pameti, takze ten vypocet by na rychlost nemel mit vliv. Nezkousel sem to, ale verim, ze pouziti iteratoru bude v tomto pripade pomalejsi nez "klasicky" for cyklus. Bohužel ale, tento přístup nelze použít u spousty jiných dost často používaných kontejnerů, které alokují pamět nespojitě. Např list nebo set atp. Takže pokud nejde vyloženě o rychlost je někdy pohodlnější použít metodu COPY & PASTE, když už to bylo někde předtím napsané, třeba pro jiný kontejner.
Přidej příspěvek
Ano, opravdu chci reagovat → zobrazí formulář pro přidání příspěvku
×Vložení zdrojáku
×Vložení obrázku
×Vložení videa
Uživatelé prohlížející si toto vlákno
Podobná vlákna
Inicializace struktury v konstruktoru třídy — založil hlucheucho
Inicializace pointeru v konstruktoru třídy — založil hlucheucho
Inicializace dvojrozměrného pole v Delphi7 — založil Gonzo
Inicializace pole v konstruktoru — založil kadet
Rychlá inicializace pole v konstruktoru - jak? — založil Huge
Moderátoři diskuze