|
Ha rendezhetöek az elemeid akkor rendezve pakold össze és logaritkmikus keresés.
Ha nem, akkor marad a lineáris.
|
|
|
akkor meg már inkább kézzel végigtolom
|
|
|
Ha engem kérdezel, az std::find is végigiterál és operator==

Szerk.:
Kód: template<class InputIterator, class T>
InputIterator find ( InputIterator first, InputIterator last, const T& value )
{
for ( ;first!=last; first++) if ( *first==value ) break;
return first;
}
http://www.cplusplus.com/reference/algorithm/find/
|
|
|
csak egy kis apróság: Ha van egy vectorom és meg akarom nézni, hogy egy elem benne van-e, akkor végigiteráljak rajta és minden egyes elemre == operátor, vagy std::find? (nyilván sebesség a fontos, mindkettő ugyan azt a feladatot látja el)
|
|
|
Sziasztok, segítséget szertnék kérni tőletek! Van egy majdnem kész játékom és, hogy igényesen tudjam megosztani az ismerőseimmel szükségem lenne egy telepítő környezetre. A gondom az, hogy még csak nem is érintettem ezt a területet így azt sem tudom mit keressek? VC 2008 ee alatt fejlesztek. Tutorialt, könyvcímet, linket, és bármilyen segítséget megköszönök ami érínti ezt a témát..
|
|
|
Én ezzel vigyzánék...egyébként a legtöbb konténerre igaz, hogy az erase-elt iterátor invaliddá válik.
Egy átláthatóbb megoldás ez, láncolt szerkezetekre (list, set, map):
Kód: iterator it = cont.begin();
iterator next;
while( it != cont.end() )
{
next = it;
++next;
cont.erase(it);
it = next;
}
|
|
|
ezért keresek megoldást  (delete nélkül szintén rossz amúgy). az erase visszatérő értéke meg nem iterátor (mint mondjuk a vector esetében)
szerk.:
Remélhetőleg így jó
Kód: std::map<std::string,ContentItem*>::iterator i = m_Contents.begin();
std::map<std::string,ContentItem*>::iterator end = m_Contents.end();
while (i != end)
{
if (i->second->m_RefCount == 0)
{
delete i->second;
m_Contents.erase(i++);
}
else
++i;
}
Ezt a hozzászólást Pretender módosította (2011.04.15 21:17 GMT+1 óra, ---)
|
|
|
nem lehet, hogy törlés után az iterátor használhatatlanná válik?
|
|
|
std::map-ből akarok kivenni elemeket egy feltétel szerint
Kód: std::map<std::string,ContentItem*>::iterator i;
for (i = m_Contents.begin(); i != m_Contents.end(); i++)
{
if (i->second->m_RefCount == 0)
{
delete i->second;
m_Contents.erase(i);
}
}
1 elemmel tesztelek, ezután a rész után "elszáll" a program (konkrétan nincs hibaüzenet, de kilép magától, valószínűleg az iterátor lesz a bajos  )
|
|
|
Idézet Joga :
scoped_ptr a barátod
Kód: std::vector<boost::scoped_ptr<MyObject> > myVector;
Kicsit fura, de végülis logikus megoldás...
|
|
|
scoped_ptr a barátod
|
|
|
Persze az alábbi a várt eredményt adja, csak kicsit körülményes a "manuális" felszabadítás miatt...
Kód: MyObject *myPointer;
std::vector<MyObject *> myVector;
// a pointer, vector és az objektumok is változtathatóak
const MyObject *myPointer;
std::vector<const MyObject *> myVector;
// a pointer és a vector változtathatóak, az objektumok nem
MyObject *const myPointer;
const std::vector<MyObject *> myVector;
// a pointer és a vector nem változtathatóak, az objektumok viszont igen
szerk: De most így végiggondolva, ez a logikus felépítés...
Ezt a hozzászólást bit.0x8000 módosította (2011.04.12 20:57 GMT+1 óra, ---)
|
|
|
Mert a vektor az már egy interfészt definiál amin keresztül kommunikálhatsz vele. Az meg hogy const vektorban elemet cserélj az nem megengedett müvelet (söt, nyelvi szinten sem, hacsaknem mutable változókat használna).
Kód: class Apple
{
mutable int t[10];
public:
int& get(int i) const {
return t[i];
}
};
int main()
{
Apple a;
const Apple& ca = a;
ca.get(2) = 6;
std::cout << ca.get(2) << "\n";
system("pause");
return 0;
}
Egy ilyen elfedö osztállyal esetleg meg tudnád oldani. Ez viszont egy kvanagy "támadási felület", nemis értem mért van egyáltalán ez a mutable kulcsszó (nekem sose kellett használnom).
|
|
|
Idézet Asylum :
Az utolsóban mért változtathatóak az objektumok?
Hát ez az, hogy a pointer-nél változtatható, a vector-nál nem...
|
|
|
Az utolsóban mért változtathatóak az objektumok?
Csak bizonyos metódusokat pedig nem lehet letiltani. Vagy minden elérhetö, vagy csak a const-ok.
|
|
|
Ahogy próbáltam, a const mégis tranzitívnek tűnik, viszont ez felvet egy másik problémát: mi van, ha azt akarom, hogy a külső vector-ban ne lehessen elemet hozzáadni, törölni, cserélni, viszont a már bent lévő elem objektumok tulajdonságai változtathatóak legyenek?
szerk: Azt a fajta működést hiányolom, ami a pointer-eknél van:
Kód: MyObject *myPointer;
std::vector<MyObject> myVector;
// a pointer, vector és az objektumok is változtathatóak
const MyObject *myPointer;
std::vector<const MyObject> myVector;
// a pointer és a vector változtathatóak, az objektumok nem
MyObject *const myPointer;
const std::vector<MyObject> myVector;
// a pointer és a vector nem változtathatóak, az objektumok viszont igen
Ezt a hozzászólást bit.0x8000 módosította (2011.04.12 20:40 GMT+1 óra, ---)
|
|
|
A const vektor nem fogja engedni, hogy változtasd az elemeit, még ha azok vektorok is, tehát ilyenkor sztem a [] operátor konstans referenciát fog visszaadni
|
|
|
Azzal van a gondom, hogy a const szerintem nem tranzitív, azaz a belső vector-okban tudok változtatni - vagy nem így van?
|
|
|
szebb (a kódod egyébként jó):
Kód: typedef std::vector<std::vector<unsigned> > myunsignedmatrix;
|
|
|
ez a jó megoldás
|
|
|
Vector-okból készült vector-t vajon hogyan kéne átadni másik objektumnak, úgy, hogy az ő számára konstansok legyenek?
Most így használom:
Kód: std::vector<std::vector<unsigned> > board;
const std::vector<std::vector<unsigned> > &getBoard();
Van valami jobb/szebb megoldás?
|
|
|
De szerintem ez így logikus
|
|
|
Annyi osztály (és így statikus tag) lesz, ahány típussal használod a template-et (illetve ugyanazzal a típussal is lehet több)...
|
|
|
Idézet bit.0x8000 :
(szerk: Nézd meg mi történik, ha egy template osztályban statikus tagot hozol létre... )
Mi történne?
|
|
|
Idézet Pretender :
de ha new T van, akkor arról nem tudja a fordító, hogy az ContentItem típusú, így nincs/nincsenek megfelelő konstruktora és változói... vagy rosszul értettem valamit 
szerk.:
tévedtem, így tényleg jó... nem mertem így kipróbálni, mondom úgyse engedi a fordító kösz
Itt az a trükk, hogy a template-ek (a macro-khoz hasonlóan) a fordítónak "szólnak", ami normál osztályokat és függvényeket gyárt belőlük - ezért engedi ezt a fordító, viszont ha nem talál egy függvényt vagy változót, biztosan reklamál...
(szerk: Nézd meg mi történik, ha egy template osztályban statikus tagot hozol létre...  )
|
|
|
Anno nekem is így volt, hogy minden külön metódus, úgy viszont külön std::vector volt minden egyes content típusra (pl. textures,models, stb.), így még a keresési is gyorsabb volt. Átnézem még majd azt a tervet, majd látom.
|
|
|
És ha mondjuk cubemapet akar bteölteni a user, de nem tudja mi az a DDS, csak van 6 db BMP-je?  Addig gondold át a dolgot amig nem épitesz fel erre egy egész rendszert. A dummyban külön metódus van mindenre, ez teljesen tökugyanolyanugyanjól használható csak nekellenek a nyamvadt kacsacsörök:
Kód: effect = Content.LoadMaterial("effects/ultimaterenderer.fx");
texture = Content.LoadTexture("textures/tile.jpg");
Ha meg a user valami újat akar, akkor egyszerüen:
Kód: class MyContentManager : public DummyFramework::CContentManager
{
public:
LPDIRECT3DCUBETEXTURE9 LoadCubeTexture(const std::string files[]) { ... }
};
Ennyi.. C++ -ra ne eröltesd rá a c#-féle abberációkat.
|
|
|
jaja, végül ez lett a megoldás, csak nem tudtam, hogy a fordító engedi a new T(...)-t, meg a fgvhívást.  amúgy végiggondoltam, és simán megoldható, hogy ne kelljen neki több paraméter (textúrát,,modellt,meg shadert fogok így alapvetően betölteni; a shadert meg majd lefordítom előre, és csak egy bináris fájlt kell megnyitni, így nincs szükség a vs és ps verzióra, vagy valami ilyesmi...)
Mellesleg xna-ban is így csinálták meg, dehát microsoft...  valamelyik nap belenéztem a 4.0-ba... Vannak ott jó ötletek, de nyilván vannak rosszak is
|
|
|
Kód: #include <iostream>
#include <string>
class ContentItem
{
public:
ContentItem() {}
ContentItem(const std::string& file) {
std::cout << "ContentItem::ContentItem(" << file << ")\n"; }
virtual ~ContentItem() {};
};
class Texture2D : public ContentItem
{
public:
Texture2D(const std::string& file) {
std::cout << "Texture2D::Texture2D(" << file << ")\n"; }
};
class Mesh : public ContentItem
{
public:
Mesh(const std::string& file) {
std::cout << "Mesh::Mesh(" << file << ")\n"; }
};
template <typename T>
T* Load(const std::string& file)
{
T* ret = new T(file);
return ret;
}
int main()
{
Texture2D* tex1 = Load<Texture2D>("mytex.png");
delete tex1;
system("pause");
return 0;
}
Egyébként nem javasolnám ezt a módszert mert hihetetlen szopás és undorító kód lesz a vége (dehát ez a microfost mért is érdekelné a winapi után...). Arról nem is beszélve, hogy ha vmelyik contentnek több paraméter kell, akkor a Load<T> függvényt kell átirni...tehát rugalmatlan is.
|
|
|
de ha new T van, akkor arról nem tudja a fordító, hogy az ContentItem típusú, így nincs/nincsenek megfelelő konstruktora és változói... vagy rosszul értettem valamit
szerk.:
tévedtem, így tényleg jó... nem mertem így kipróbálni, mondom úgyse engedi a fordító  kösz
|
|
|
Inkább new T kellene nem?
Gondolom a T típusok származnak ContentItem-ből és nem fordítva.
|
|
|
van egy ContenItem osztályom, aminek van 2 virtual (tehát overrideolható) metódusa. Ebből az osztályból örököltetek mondjuk egy Texture osztályt. Azt szeretném kérdezni, hogy hogyan lehetne megoldani azt, hogy egyetlen egy ilyen "általános" Load metódus legyen?
Próbálkoztam template-el (és akkor valami olyasmi volt, mint xna-ban: Load<T>  , de akkor nem a megfelelő metódusokat hívta meg, csak simán a ContentItem-ét (persze valószínű, h rosszul használom  )
szerk.:
Olyat nem csináltak, hogy a template-nek meg lehessen adni, hogy milyen "fajta" lehet, ugye?  (itt most a ContentItem-re gondoltam, hogy olyan típusúnak kellene lennie a T-nek...)
Ilyesmivel próbálkoztam, ez így nyilvánvalóan nem jó:
Kód: template <typename T>
inline T* Load(const std::string& p_Path)
{
ContentItem* item = 0;
std::map<std::string,ContentItem*>::iterator i(m_Contents.lower_bound(p_Path));
if (i == m_Contents.end())
{
item = new ContentItem(p_Path,m_Device);
m_Contents.insert(i,make_pair(p_Path,item));
}
else
{
item = i->second;
}
if (!((T*)item)->AddRef())
return 0;
return (T*)item;
}
szerk.2:
vagy ilyet egyáltalán nem is lehet...
Ezt a hozzászólást Pretender módosította (2011.04.02 14:36 GMT+1 óra, ---)
|
|
|
lényeg, hogy a kacsák előtt mindig legyen víz és kész...
|
|
|
Idézet lezli01 :
én nem a cpp-t helyeztem más nyelv elé, hanem a külön implementálást az inline elé... 
u.i.: persze, hogy tudsz sor kód nélkül, mivel már előtted valaki megírta! 
úgy értettem, hogy a kollégának meg tudom mondani, hogy mi lesz az interfész, anélkül, hogy bármit is írnék belőle. ezért mondtam a csapatmunkát ilyen szempontból gyenge érvnek.
|
|
|
én nem a cpp-t helyeztem más nyelv elé, hanem a külön implementálást az inline elé...
u.i.: persze, hogy tudsz sor kód nélkül, mivel már előtted valaki megírta!
|
|
|
Idézet lezli01 :
Másik előnye, ha külön írod a headert és az implementációt a csapatmunkában keresendő... A kész, csak deklarációkat tartalmazó header-t átnyújtva a társadnak, aki majd használni szeretné a te osztályodat, már láthatja milyen metódusokat használhat, milyen funkciókat fog neki nyújtani és el kezdhet programozni, mialatt vele párhuzamosan írod a header implementációját...
jó, ez azért elég satnya érv, valljuk be. én java-ban is meg tudom mondani, hogy mi lesz az interfészem, úgy, hogy egy sor kódot nem írtam még meg az osztályból.
|
|
|
most amúgy azt magyarázza mindenki, hogy miért dugunk ... azért mert így a helyes és jó...
|
|
|
Másik előnye, ha külön írod a headert és az implementációt a csapatmunkában keresendő... A kész, csak deklarációkat tartalmazó header-t átnyújtva a társadnak, aki majd használni szeretné a te osztályodat, már láthatja milyen metódusokat használhat, milyen funkciókat fog neki nyújtani és el kezdhet programozni, mialatt vele párhuzamosan írod a header implementációját...
|
|
|
|
Azért, mert valami nem 2011-ben jött létre, nem jelenti azt, hogy oldschool  Hacsaknem a dátumra utaltál és nem az alkalmazott mechanizmusra. Akkor elfogadható a kritika
|
|
|
Idézet petyur :
Az oldschool kicsit erős...
Miért lenne, elég, ha csak azt nézed, hogy mikor született a nyelv...
Amúgy szerintem analógiát lehet vonni a C++ és a GNU/Linux-ok felépítése között: elsőre körülményesnek tűnik, de ennek megvannak az okai és az előnyei (például a rugalmasság).
|
|
|
Szerintem ez a header+implementáció szétválasztás az egyik legsokoldalúbbá és (most készüljetek a szép szóra) "legújrafelhasználhatóbbá" teszi a nyelvet. Cserebere alapon lehet javítani úgy, hogy a kedves vevőnek kiküldött interface változatlan marad (azaz nem kell neki is mindent kicserélni), észre sem veszi, hogy új implementáció dobog a kód alatt, amennyiben javításra, vagy "upgrade-re" van szükség.
Az oldschool kicsit erős... aki nem érzi az erősségét, annak még van mit tanulni.
|
|
|
Idézet bit.0x8000 :
Szóval van ráció ebben a kialakításban, még ha kicsit oldschool is...
Oldschool ám a kutyafüle; ezek az új "programnyelvek" azt hiszik hogy X év konvencióit csak úgy fel lehet rúgni (és egyébként a kutya nem használná öket ha nem lennének 2 klikkel programozhatóak).
|
|
|
persze, hogy van ráció, dehát omfg, nehogy már nekem kelljen kézzel leírogatnom, 2011ben...
|
|
|
Szóval van ráció ebben a kialakításban, még ha kicsit oldschool is...
|
|
|
Meg azért hogy el legyen választva az interfész és a megvalósítás (ezáltal kicserélhetövé téve).
|
|
|
Gondolom ez kezdetben azért alakult így ki, hogy már lefordított binárisokat is lehessen linkelni... (Hiszen ebben az esetben a header írja le az interfészt.)
|
|
|
en amugy a header file-ok legnagyobb pozitivumanak a gyakorlatilag teljes, kikenyszeritett dokumentaciot tartom, egy java vagy c# forras tomeny kaosz elso ranezesre (meg tobbnyire masodikra, harmadikra is)
persze ehhez kell a normalis fv- es valtozoelnevezes meg commenteles is
|
|
|
Mivel a linkelés a fordítási fázisok végén van, ezért a már lefordított CPP fájlok nem mennek át a 7 fázis nagyján
|
|
|
Nem is beszélve az (egyik?) eredeti céljáról a külön .h,.c/.cpp fileoknak, hogy az amúgy is iszonyat lassú fordítást egy kicsit gyorsítsák. Ami a headerbe van írva, mindig újra kell fordítani, ha a header változik, és mindent mást is, amibe include-olva van, így nagyon nehézkes, ha egy függvény próbálgatásakor perceket kell esetleg várni, hogy minden forduljon. Ha a .cpp-ben változtatunk, csak azt az egyet fordítja és linkel. Állítólag így is végig kell menni a kódon minimum hétszer, mire mindent ki tud silabizálni a fordító. Itt van erről valami, de nem mintha olyan érdekes lenne:
link
|
|