Herzlich Willkommen, lieber Gast!
  Sie befinden sich hier:

  Forum » C / C++ (ANSI-Standard) » Inline Klasse / Ersetzung geht nicht richtig

Forum | Hilfe | Team | Links | Impressum | > Suche < | Mitglieder | Registrieren | Einloggen
  Quicklinks: MSDN-Online || STL || clib Reference Grundlagen || Literatur || E-Books || Zubehör || > F.A.Q. < || Downloads   

Autor Thread - Seiten: > 1 <
000
11.01.2006, 13:08 Uhr
~ADOOM
Gast


Hallo,

Folgende Problemstellung:


Code:

class Integer
{
public:
    Integer(void);
    Integer(const int value);
    Integer(const Integer &var);
    ~Integer(void);

        int operator + (Integer var) const;
    
    const Float sepp() const;
// cast operatoren
    operator Float() const; // kein schreibfehler!!! Float pendant zu float wie Integer zu int
    
private:
    int value;
};

inline const Float Integer::sepp() const{
    return value;
}

inline int Integer::operator + (Integer var) const
{
    return (this->value + var.value);
}

//V 1
inline Integer::operator Float() const
{    
    const Float puff(value);
    return puff;
}
//V 2 (liefern beide das gleiche problem)
inline Integer::operator Float() const
{
    return value;
}




Diese Klasse ist natuerlich noch groesser, was aber fuer die Frage belanglos ist.
Main vollstaendig:


Code:

int main(void)
{
    Integer i(5);
    Integer j(6);
    Float f(3.7f);
    Char *c = new Char[100];
    Double d(7.3849);
    Double dd(2.4233);
    utils::StopWatch *sw = new utils::StopWatch();
    volatile int k=0;
    double time;
    ofstream file("inlineRTTI.csv", ios::out|ios::binary|ios::beg);
    int l=0;
    while (l < 100)
    {
        sw->reset();
        sw->start();
        while(k < 4000000000)
        {
            i += 1;
            i += j+2;
            i -= 3;
            i -= j+3;
            i *= 4;
            --i;
            i *= j+4;
            i /= 6;
            i /= j+5;
            ++i;

            f +=   (Float) i; // <------ !!!!!!!!!!! operator Float() const
            f = f + 0.3f;
            f += 2.1f;
            f -= 1.2f;
            f /= 0.234f;
            
            c[0] = i+1;
            c[1] = i+2;
            
            if (i == j)
                f  = 9.34f;
            else
                i = 345;

            d /= dd;
            d *= dd;
            d += dd;
            d -= dd; //*/
            
            ++k;
        }

        time = sw->getTime();
        file << time << ";" << endl;
        k=0;
        ++l;
    }
    file.close();
    cout << i << j << c << f << d << dd;
/*    cout << "fertig" << endl;
    char fake[100];
    cin >> fake;*/
    return 0;
}



Bei der makierten Zeile wird entsprechend der cast operator Aufgerufen. Dieser ist allerdings Inline definiert und sollte bei den entsprechenden optimierungseinstellungen ersetzt werden.

Ich benutze den VC++ 7, mit den einstellungen:
Full Optimization (/Ox)
Global Optimizations yes (/Og)
Inline Function Expansion only _inline ODER any siutable
Favor Fast Code

Die Inline Ersetzung sollte also an sein. Bei funktionen die eine Referenz auf sich selbst zurueckgeben und ansonsten nicht viel machen (siehe operator +) passiert dies auch, nur bei dem Cast operator bzw. bei Methoden die Beispielsweise in der Methodendefinition Objekte erstellen (siehe operator Float() const) wird immer noch ein call (sowohl Variante V1 als auch V2 und bei Integer::sepp()) ausgefuehrt:

; 50 : f += (Float) i;

lea ecx, DWORD PTR $T109043[esp+216]
lea esi, DWORD PTR [edx+eax+1]
push ecx
lea ecx, DWORD PTR _i$[esp+220]
mov DWORD PTR _i$[esp+220], esi
call ??BInteger@@QBE?AVFloat@@XZ ; Integer::operator Float <-- das ist schlecht / langsam


; 50 : f += i.sepp();
lea ecx, DWORD PTR $T109036[esp+224]
lea esi, DWORD PTR [edx+eax+1]
push ecx
lea ecx, DWORD PTR _i$[esp+228]
mov DWORD PTR _i$[esp+228], esi
call ?sepp@Integer@@QBE?BVFloat@@XZ ; Integer::sepp


gibt es eine Moeglichkeit die Methoden anders zu formulieren so dass entsprechend eine ersetzung anstatt eines sprunges vorgenommen wird / bzw gibt es eine Kompilereinstellung die dies bezweckt? (die Klasse soll in Float castbar sein (nicht float))

(der call macht die ganze sache ziemlich langsam)


thx for help
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
001
11.01.2006, 14:20 Uhr
(un)wissender
Niveauwart


Also erstmal sollte man die impliziten Umwandlungs-Operator mal weglassen. Willst du es aber dennoch:

V1 und V2 zusammen verletzen die"One Definition Rule". Kompilieren geht nicht.
Ansonsten kannste auch noch __forceinline verwenden, für VC++.
Generell findet wohl mindestens ein Konstruktoraufruf und eine Konvertierung von int ->float statt , die in der Default-Einstellung recht aufwändig ist. Ev. sieht Vc++ das als zu groß zum inlinen an.

Btw.:
operator + gibt auch keine Selbstreferenz zurück (was er aber tun sollte) sondern einen int.
--
Wer früher stirbt ist länger tot.

Dieser Post wurde am 11.01.2006 um 14:21 Uhr von (un)wissender editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
002
11.01.2006, 14:40 Uhr
~ADOOM
Gast


V1 und V2 waren nur als beispiele gedacht fuer das kompilieren habe natuerlich immer eine eindeutige variante,

der + operator sollte auf KEINEN FALL eine selbstreferenz zurueck geben
was du gemeint hast war eine KOPIE
Integer I(5);
int baum = I+5;
wuerde nicht funktionnieren entweder baum erhaelt den falschen wert oder I aendert seinen wert.

ich hab das prob jetzt geloest
statt
operator Float();
operator const Float &();
und alles wird gut :-)
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
003
11.01.2006, 20:42 Uhr
stephanw
localhorst



C++:
Integer I(5);
int baum = I+5;



Dafür ist es besser, eine Nicht-Member-Funktion als Operator bereitzustellen und diesen dann in zwei Versionen:

C++:
int operator+(const Integer& a, int b);
// und
int operator+(int b, const Integer& a); // dieser geht nicht als Member, da erster Op. vom Typ int und nicht Integer



Generell scheint es eine gute Konvention zu sein, alle Operatoren, die ein neues Objekt erzeugen, nicht als Member zu definieren. Dagegen sollten alle die als Member definiert werden, die das Objekt selbst verändern, z.B. der operator+=(int) .

@(un)wissender: Rückgabe einer Selbst-Referenz ist doch nur sinnvoll, wenn man verkettete Ausdrücke schreiben will: vec.reverse().normalize(); Aber wozu das bei "+" oder "+=" ?
--
Reden ist Schweigen und Silber ist Gold.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
004
12.01.2006, 09:46 Uhr
(un)wissender
Niveauwart


Ja ja, ich habe mich versehen, klar ist ein constantes Objekt zurückzugeben (bei +).
Ah bei += tut man das aber (do as the ints do). Ist ja auch nicht const
--
Wer früher stirbt ist länger tot.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
Seiten: > 1 <     [ C / C++ (ANSI-Standard) ]  


ThWBoard 2.73 FloSoft-Edition
© by Paul Baecher & Felix Gonschorek (www.thwboard.de)

Anpassungen des Forums
© by Flo-Soft (www.flo-soft.de)

Sie sind Besucher: