Kezdőlap › Fórumok › Programozás › C++ probléma
- This topic has 12 hozzászólás, 3 résztvevő, and was last updated 17 years, 8 months telt el by
pointux.
-
SzerzőBejegyzés
-
2007-11-02-13:39 #2139152
Helyesen így néz ki a kód:
Code:class Vector3D {
/* … */
}Vector3D operator* ( const Vector3D & _src1, const Vector3D & _src2 ) {
Vector3D * _dst = NULL;try {
_dst = new Vector3D ( /* … */ );
} catch ( /* … */ ) {
/* … */
}std::auto_ptr __dst ( _dst ); // (1)
/* … */return * _dst;
}Az (1) nélkül szivárgás következhet be a következő esetben:
Code:Vector3D _v_dst;_v_dst = _v_src1 * _v_src2;
A szivárgás, persze elkerülhető így:
Code:Vector3D *_v_dst;_v_dst = &_v_src1 * _v_src2;
delete _v_dst;
Az (1) esetében az egyébként szükségtelen delete operátor kiadása után nullázni kell a pointert:
Code:Vector3D * _v_dstdelete _v_dst;
_v_dst = NULL;mert máskülönben a létrehozott Vector3D objektumon az „élettartam-lejárta” után a program megpróbálja lefuttatni rajta a free függvényt. Ez azért kellemetlen, mert a fent említett memória mutató egy már felszabadított területre mutat.
Persze nem lenne gond, ha a C nyelv biztonságosabbra lenne írva…
Ennyi már elég lenne:Code:void delete ( void ** _ptr)Mert így már lehetne nullázni. (Noha ez fél megoldás, mert lehetne mutató mutatója is.)
Persze az „stl” is meg lehetett volna normálisan írni, mert nem ez az egy eset, ami azonnal feloldatlan kivételt okoz… úgyhogy mindenki azt tanítja, de aki ad magára nem használja, legfeljebb feltételekkel.
2007-11-02-13:39 #2139153Helyesen így néz ki a kód:
Code:class Vector3D {
/* … */
}Vector3D operator* ( const Vector3D & _src1, const Vector3D & _src2 ) {
Vector3D * _dst = NULL;try {
_dst = new Vector3D ( /* … */ );
} catch ( /* … */ ) {
/* … */
}std::auto_ptr __dst ( _dst ); // (1)
/* … */return * _dst;
}Az (1) nélkül szivárgás következhet be a következő esetben:
Code:Vector3D _v_dst;_v_dst = _v_src1 * _v_src2;
A szivárgás, persze elkerülhető így:
Code:Vector3D *_v_dst;_v_dst = &_v_src1 * _v_src2;
delete _v_dst;
Az (1) esetében az egyébként szükségtelen delete operátor kiadása után nullázni kell a pointert:
Code:Vector3D * _v_dstdelete _v_dst;
_v_dst = NULL;mert máskülönben a létrehozott Vector3D objektumon az „élettartam-lejárta” után a program megpróbálja lefuttatni rajta a free függvényt. Ez azért kellemetlen, mert a fent említett memória mutató egy már felszabadított területre mutat.
Persze nem lenne gond, ha a C nyelv biztonságosabbra lenne írva…
Ennyi már elég lenne:Code:void delete ( void ** _ptr)Mert így már lehetne nullázni. (Noha ez fél megoldás, mert lehetne mutató mutatója is.)
Persze az „stl” is meg lehetett volna normálisan írni, mert nem ez az egy eset, ami azonnal feloldatlan kivételt okoz… úgyhogy mindenki azt tanítja, de aki ad magára nem használja, legfeljebb feltételekkel.
2007-11-02-15:21 #2139154FLINX wrote:Üdv.Csatoltam egy C++ kódot, amire a g++ a következő hibaüzenetet adja:
Code:test.cpp: In member function ‘bool Sphere::Intersect(const Ray&, HitRec*)’:
test.cpp:74: error: passing ‘const Vector3D’ as ‘this’ argument of ‘Vector3D Vector3D::operator-(Vector3D)’ discards qualifiers
test.cpp:76: error: passing ‘const Vector3D’ as ‘this’ argument of ‘float Vector3D::operator*(Vector3D)’ discards qualifiers
test.cpp:97: error: passing ‘const Vector3D’ as ‘this’ argument of ‘Vector3D Vector3D::operator*(float)’ discards qualifiers
test.cpp:97: error: passing ‘const Vector3D’ as ‘this’ argument of ‘Vector3D Vector3D::operator+(Vector3D)’ discards qualifiersAmi röveden annyi, hogy az említett függvényben egy konstans Vector3D objektumot nem tud átadni this argumentumként a felsorolt operátor függvényeknek…
A C++ nyelvben ha egy objektom konstans minősítésű (itt: konstans paraméter), akkor csak a konstans metódusokat lehet elérni, jelenleg ez a baja a GCC fordítónak. Megoldás: használj ‘const’ minősítőt az objektumot nem módosító metódusoknál.
Code:Vector3D operator=(const Vector3D& v); // Módosít, nem konstans metódusVector3D operator+( Vector3D v) const; // Nem módosít, ‘const’ utóminősítőt kapott
Vector3D operator-( Vector3D v) const;Vector3D operator*(const float f) const ;
Vector3D operator/(const float f) const;float operator*(const Vector3D v) const {return x*v.x+y*v.y+z*v.z;} //skaláris szorzat
float Length() const {return (float)sqrt(x*x+y*y+z*z);}
float* GetArray() const {return &x; } // struktúra kezdőcíme (nem kontsans objektumból meghívva)
const float* GetArray() const {return &x; } // struktúra kezdőcíme (konstans objektumból meghívva)FLINX wrote:A kódban máshol használom ezeket az operátor függvényeket, és arra nem jelent hibát…
Pedig elvileg itt is ugyanolyan Vector3D illetve float argumentumokkal próbálok kiértékelni műveleteket, mint máshol.Ez azért van.mert a többi helyen nem konstans objektum metódusát hívod, a ‘bool Sphere::Intersect(const Ray&, HitRec*)’ metódus ‘ray’ paramétere meg konstans. Ha a fenti minősitőket hsználod, akkor már nem lesz gond.
2007-11-02-15:21 #2139155FLINX wrote:Üdv.Csatoltam egy C++ kódot, amire a g++ a következő hibaüzenetet adja:
Code:test.cpp: In member function ‘bool Sphere::Intersect(const Ray&, HitRec*)’:
test.cpp:74: error: passing ‘const Vector3D’ as ‘this’ argument of ‘Vector3D Vector3D::operator-(Vector3D)’ discards qualifiers
test.cpp:76: error: passing ‘const Vector3D’ as ‘this’ argument of ‘float Vector3D::operator*(Vector3D)’ discards qualifiers
test.cpp:97: error: passing ‘const Vector3D’ as ‘this’ argument of ‘Vector3D Vector3D::operator*(float)’ discards qualifiers
test.cpp:97: error: passing ‘const Vector3D’ as ‘this’ argument of ‘Vector3D Vector3D::operator+(Vector3D)’ discards qualifiersAmi röveden annyi, hogy az említett függvényben egy konstans Vector3D objektumot nem tud átadni this argumentumként a felsorolt operátor függvényeknek…
A C++ nyelvben ha egy objektom konstans minősítésű (itt: konstans paraméter), akkor csak a konstans metódusokat lehet elérni, jelenleg ez a baja a GCC fordítónak. Megoldás: használj ‘const’ minősítőt az objektumot nem módosító metódusoknál.
Code:Vector3D operator=(const Vector3D& v); // Módosít, nem konstans metódusVector3D operator+( Vector3D v) const; // Nem módosít, ‘const’ utóminősítőt kapott
Vector3D operator-( Vector3D v) const;Vector3D operator*(const float f) const ;
Vector3D operator/(const float f) const;float operator*(const Vector3D v) const {return x*v.x+y*v.y+z*v.z;} //skaláris szorzat
float Length() const {return (float)sqrt(x*x+y*y+z*z);}
float* GetArray() const {return &x; } // struktúra kezdőcíme (nem kontsans objektumból meghívva)
const float* GetArray() const {return &x; } // struktúra kezdőcíme (konstans objektumból meghívva)FLINX wrote:A kódban máshol használom ezeket az operátor függvényeket, és arra nem jelent hibát…
Pedig elvileg itt is ugyanolyan Vector3D illetve float argumentumokkal próbálok kiértékelni műveleteket, mint máshol.Ez azért van.mert a többi helyen nem konstans objektum metódusát hívod, a ‘bool Sphere::Intersect(const Ray&, HitRec*)’ metódus ‘ray’ paramétere meg konstans. Ha a fenti minősitőket hsználod, akkor már nem lesz gond.
2007-11-02-16:48 #2139156vizsla wrote:Helyesen így néz ki a kód:Code:class Vector3D {
/* … */
}Vector3D operator* ( const Vector3D & _src1, const Vector3D & _src2 ) {
Vector3D * _dst = NULL;try {
_dst = new Vector3D ( /* … */ );
} catch ( /* … */ ) {
/* … */
}std::auto_ptr __dst ( _dst ); // (1)
/* … */return * _dst;
}Ha feladjuk a szálbiztos felépítést, akkor egyszerűbb és hatékonyabb ez a kód:
Code:class Vector3D {
/* … */
}Vector3D operator* ( const Vector3D & _src1, const Vector3D & _src2 ) {
static Vector3D _dst;/* … */
return _dst;
}De így se kerülhetjük el a visszatérési érték egyenkénti másolgatását, hacsak nem használunk tömböt az egyenkénti vagy csoportos műveletekhez:
Code:// Absztakt osztály
class Vector3D {
public:
virtual ~Vector3D ();virtual Vector3D operator* ( const Vector3D & _src1, const Vector3D & _src2 ) const=0;
};// A klasszikus Vector3D implementáció; független
class Vector3DStatic: public Vector3D {
private:
float x;
float y;
float z;
public:
virtual ~Vector3DStatic ();virtual Vector3D operator* ( const Vector3D & _src1, const Vector3D & _src2 ) const;
Vector3DStatic operator* ( const Vector3DStatic & _src1, const Vector3DStatic & _src2 ) const;
};// Egy Vector3D tömb eleme, függ a tömbtöl, de viszont gyors és hatékony
class Vector3DArrayItem: public Vector3D {
private:
float *item; // float triplet, mutató a Vector3DArray::store egyik elemére
public:
virtual ~Vector3DArrayItem ();virtual Vector3D operator* ( const Vector3D & _src1, const Vector3D & _src2 ) const;
Vector3DArrayItem operator* ( const Vector3DArrayItem & _src1, const Vector3DArrayItem & _src2 ) const;
};// A Vector3D tömb implementációja
class Vector3DArray {
private:
size_t size;
float *store; // Hossz: size*3;
public:
Vector3DArray (size_t _size);
~Vector3DArray ();Vector3DArrayItem operator[] (size_t _pos) const;
float[3] raw (size_t _pos);
Vector3DArray operator* ( const Vector3DArray & _src1, const Vector3DArray & _src2 ) const;
Vector3DArray subarray (size_t _start size_t _end) const;
};2007-11-02-16:48 #2139157vizsla wrote:Helyesen így néz ki a kód:Code:class Vector3D {
/* … */
}Vector3D operator* ( const Vector3D & _src1, const Vector3D & _src2 ) {
Vector3D * _dst = NULL;try {
_dst = new Vector3D ( /* … */ );
} catch ( /* … */ ) {
/* … */
}std::auto_ptr __dst ( _dst ); // (1)
/* … */return * _dst;
}Ha feladjuk a szálbiztos felépítést, akkor egyszerűbb és hatékonyabb ez a kód:
Code:class Vector3D {
/* … */
}Vector3D operator* ( const Vector3D & _src1, const Vector3D & _src2 ) {
static Vector3D _dst;/* … */
return _dst;
}De így se kerülhetjük el a visszatérési érték egyenkénti másolgatását, hacsak nem használunk tömböt az egyenkénti vagy csoportos műveletekhez:
Code:// Absztakt osztály
class Vector3D {
public:
virtual ~Vector3D ();virtual Vector3D operator* ( const Vector3D & _src1, const Vector3D & _src2 ) const=0;
};// A klasszikus Vector3D implementáció; független
class Vector3DStatic: public Vector3D {
private:
float x;
float y;
float z;
public:
virtual ~Vector3DStatic ();virtual Vector3D operator* ( const Vector3D & _src1, const Vector3D & _src2 ) const;
Vector3DStatic operator* ( const Vector3DStatic & _src1, const Vector3DStatic & _src2 ) const;
};// Egy Vector3D tömb eleme, függ a tömbtöl, de viszont gyors és hatékony
class Vector3DArrayItem: public Vector3D {
private:
float *item; // float triplet, mutató a Vector3DArray::store egyik elemére
public:
virtual ~Vector3DArrayItem ();virtual Vector3D operator* ( const Vector3D & _src1, const Vector3D & _src2 ) const;
Vector3DArrayItem operator* ( const Vector3DArrayItem & _src1, const Vector3DArrayItem & _src2 ) const;
};// A Vector3D tömb implementációja
class Vector3DArray {
private:
size_t size;
float *store; // Hossz: size*3;
public:
Vector3DArray (size_t _size);
~Vector3DArray ();Vector3DArrayItem operator[] (size_t _pos) const;
float[3] raw (size_t _pos);
Vector3DArray operator* ( const Vector3DArray & _src1, const Vector3DArray & _src2 ) const;
Vector3DArray subarray (size_t _start size_t _end) const;
};2007-11-07-15:56 #21391581) Két jobboldali operandust kívánó kifejezésnél egyébként sem praktikus, ha a függvény tag (legfeljebb barát lehet). Gondolj csak bele egy ilyen kifejezésre v3d operator* ( float, v3d ), vagy akár v3d operator* ( v3d , v3d ). Ezeknél a típusú kifejezéseknél gond van, akár definiálsz egy const visszatérési értéket, akár egy const konvertálást hajtasz végre.
2) Persze nem kell dinamikusan létrehozni. (Bár ez szabad memória kérdése.)
Szerintem a legpraktikusabb paraméterként is referencia pointert használni. (Az operátor miatt itt nem „lehet”.)3) Egy statikus adat miatt nem kell felmondani a szálbiztos működést. Csak kell egy statikus jelző bit.
Code:if ( …::guard_bit == true ) {
/* Most nem férek hozzá… várni kell!*/
} {
…::guard_bit = true; // most a többiek várnak
/* … */
…::guard_bit = false; // most már szabad az út
}Persze kérdés, hogy ebben az esetben van-e értelme a több szálnak. Ebben az esetben van:
Code:if ( …::guard_bit == true ) {
/* Most nem férek hozzá… várni kell!*/
} {
…::guard_bit = true; // most a többiek várnak
/* Én pedig regisztrálom magam egy globális statikus listán, hogy ki vagyok és mennyi memóriát foglalok.
És ehhez az információhoz bárki hozzáférhet. */
…::guard_bit = false; // most már szabad az út
}2007-11-07-15:56 #21391591) Két jobboldali operandust kívánó kifejezésnél egyébként sem praktikus, ha a függvény tag (legfeljebb barát lehet). Gondolj csak bele egy ilyen kifejezésre v3d operator* ( float, v3d ), vagy akár v3d operator* ( v3d , v3d ). Ezeknél a típusú kifejezéseknél gond van, akár definiálsz egy const visszatérési értéket, akár egy const konvertálást hajtasz végre.
2) Persze nem kell dinamikusan létrehozni. (Bár ez szabad memória kérdése.)
Szerintem a legpraktikusabb paraméterként is referencia pointert használni. (Az operátor miatt itt nem „lehet”.)3) Egy statikus adat miatt nem kell felmondani a szálbiztos működést. Csak kell egy statikus jelző bit.
Code:if ( …::guard_bit == true ) {
/* Most nem férek hozzá… várni kell!*/
} {
…::guard_bit = true; // most a többiek várnak
/* … */
…::guard_bit = false; // most már szabad az út
}Persze kérdés, hogy ebben az esetben van-e értelme a több szálnak. Ebben az esetben van:
Code:if ( …::guard_bit == true ) {
/* Most nem férek hozzá… várni kell!*/
} {
…::guard_bit = true; // most a többiek várnak
/* Én pedig regisztrálom magam egy globális statikus listán, hogy ki vagyok és mennyi memóriát foglalok.
És ehhez az információhoz bárki hozzáférhet. */
…::guard_bit = false; // most már szabad az út
}2007-11-07-16:45 #2139160vizsla wrote:1) Két jobboldali operandust kívánó kifejezésnél egyébként sem praktikus, ha a függvény tag (legfeljebb barát lehet). Gondolj csak bele egy ilyen kifejezésre v3d operator* ( float, v3d ), vagy akár v3d operator* ( v3d , v3d ). Ezeknél a típusú kifejezéseknél gond van, akár definiálsz egy const visszatérési értéket, akár egy const konvertálást hajtasz végre.Mind igaz, de a konkrét példa nem tartalmaz sablont, így számomra nem volt lényeges a fenti probléma. Mivel a 3D-s alkalmazások 99,9%-a nem használ mást csak a float típust koordináták esetében, nincs is értelme sablonként megvalósítani a v3d osztályt.
vizsla wrote:2) Persze nem kell dinamikusan létrehozni. (Bár ez szabad memória kérdése.)
Szerintem a legpraktikusabb paraméterként is referencia pointert használni. (Az operátor miatt itt nem „lehet”.)Szerintem meg a legpraktikusabb a D nyelv garbage collector képességének használata. 🙂 Így a kódot sem kell különösebben portolni.
http://www.digitalmars.com/d/vizsla wrote:3) Egy statikus adat miatt nem kell felmondani a szálbiztos működést. Csak kell egy statikus jelző bit.A statikus jelzőbittel nem használhatsz két szálnál többet, mert a jelzőbit módosításakor nem kívánt versengés léphet fel.
Code:if ( pthread_spinlock_trylock ( …::guard_bit ) != 0 ) {
/* Most nem férek hozzá… várni kell!*/
} {
pthread_spinlock_lock (…::guard_bit ); // most a többiek várnak
/* … */
pthread_spinlock_unlock ( …::guard_bit ); // most már szabad az út
}2007-11-07-16:45 #2139161vizsla wrote:1) Két jobboldali operandust kívánó kifejezésnél egyébként sem praktikus, ha a függvény tag (legfeljebb barát lehet). Gondolj csak bele egy ilyen kifejezésre v3d operator* ( float, v3d ), vagy akár v3d operator* ( v3d , v3d ). Ezeknél a típusú kifejezéseknél gond van, akár definiálsz egy const visszatérési értéket, akár egy const konvertálást hajtasz végre.Mind igaz, de a konkrét példa nem tartalmaz sablont, így számomra nem volt lényeges a fenti probléma. Mivel a 3D-s alkalmazások 99,9%-a nem használ mást csak a float típust koordináták esetében, nincs is értelme sablonként megvalósítani a v3d osztályt.
vizsla wrote:2) Persze nem kell dinamikusan létrehozni. (Bár ez szabad memória kérdése.)
Szerintem a legpraktikusabb paraméterként is referencia pointert használni. (Az operátor miatt itt nem „lehet”.)Szerintem meg a legpraktikusabb a D nyelv garbage collector képességének használata. 🙂 Így a kódot sem kell különösebben portolni.
http://www.digitalmars.com/d/vizsla wrote:3) Egy statikus adat miatt nem kell felmondani a szálbiztos működést. Csak kell egy statikus jelző bit.A statikus jelzőbittel nem használhatsz két szálnál többet, mert a jelzőbit módosításakor nem kívánt versengés léphet fel.
Code:if ( pthread_spinlock_trylock ( …::guard_bit ) != 0 ) {
/* Most nem férek hozzá… várni kell!*/
} {
pthread_spinlock_lock (…::guard_bit ); // most a többiek várnak
/* … */
pthread_spinlock_unlock ( …::guard_bit ); // most már szabad az út
} -
SzerzőBejegyzés
- Be kell jelentkezni a hozzászóláshoz.
legutóbbi hsz