Methoden die der Comiler eh inlined: inline angeben?



  • fuer meinen Geschmack viel zu viel schreibarbeit... und verdammt hohe abhaengigkeit, quasi die ganze klasse ist inline... also mir gefaellt das garnicht (von dem total unleserlich mal abgesehen)



  • Darf ich nicht die Deklaration

    inline unsigned long length(void);

    in die string.h und die deklaration in die .cpp tun:

    unsigned long String::length(void)
    {
    return(len);
    }

    Nope. Das geht nicht. Eine inline-Methode/Funktion muss in jeder Übersetzungseinheit definiert sein.

    Es gibt drei mir bekannte Wege für die Benutzung von inline-Methoden:
    1. Methodendefinition innerhalb der Klassendefinition:

    class Foo
    {  
        public:
            // Func ist automatisch inline. Ein explizites inline ist überflüssig
            void Func()
            {
                // ...
            }
    };
    

    2. Methodendefinition außerhalb der Klassendefinition, aber im Header:

    class Foo
    {
        public:
            // das inline kann entweder bei Deklaration, bei der Definition
            // oder bei beiden stehen. 
            inline void Func();
    };
    
    inline void Foo::Func()
    {
    //...
    }
    

    3. Die Definitionen der Inline-Methoden kommen alle in eine extra .inl-Datei. Diese wird als letztes im Header inkludiert.

    // Foo.h
    class Foo
    {
        public:
            inline void Func();
            inline void Func2();
    
    };
    #include "Foo.inl"
    
    // Foo.inl
    inline void Foo::Func()
    {
    //...
    }
    inline void Foo::Func2()
    {
    //...
    }
    


  • @Lars Skiba:
    Nein das darfst du nicht, die Implementierung muss bei inline im Header stehen.

    Es gibt auch noch ein paar Ausnahmen:
    Aus MSDN (Auszug):

    You cannot inline a function if:

    The function and the caller use different types of exception handling (C++ exception handling in one, structured exception handling in the other).

    The function has a variable argument list.

    The function uses inline assembly and is not compiled with /Og, /Ox, /O1, or /O2).

    Function returns an unwindable object by value and is not compiled with /GX, /EHs, or /EHa).

    The function receives a copy-constructed object passed by value, when compiled with /GX, /EHs,, or /EHa.

    The function is recursive.

    The function is virtual.

    The program takes the address of the function.



  • Mir gefällt der 3. Weg am besten, den nehm ich 🙂



  • Das sind jeweil 3 überladene wobei die mit "TCHAR" und "String &" als Parameter nur die mit "TCHAR *" aufrufen und nur kurze Umwandelungen machen...

    Hab ich vergessen - dann eignen sie sich natürlich für Inline.

    Warum dass denn
    length ist doch nur ein return

    Eben darum ist sie ja eine von den wenigen die ich Inline machen würde.

    Was läßt dich zu dieser Regel kommen bzw. was spricht gegen inline Konstruktoren?

    Hab ich einmal den Meyers gelesen und hab ihn erst nicht verstanden...

    Also dort steht (Effective C++, Scott Meyers):

    In der Tat sind Konstruktoren und Destruktoren meist schlechte Kandidaten für inline-Funktionen, als eine oberflächliche Betrachtung vermuten lassen würde.

    Danach steht was über die von dir angesprochene Vererbung (welche wir tatsächlich hier nicht haben). Aber es steht noch mehr in diesem Buch. Und zwar müssen die Compiler im Konstruktor noch nachträglich Code einfügen, welcher zwar nicht Standard-C++ ist allerdings für das Erstellen der Objekte wichtig ist. Dieser Code würde dann natürlich ebenfalls inline werden.

    MfG SideWinder



  • Jo. Ich kenne das Buch.

    Ich finde da halt nur nichts das in die Richtung "nie nie nie" geht.
    Besonders da automatisch generierte Ctor und Dtors normalerweise immer inline generiert werden.

    Kurz: Ich kenne keine Rechtfertigung für deine Regel. Deshalb habe ich ja nachgefragt 🙂



  • Hi,

    also ich will hier mal eine Erfahrung, die ich mit inline machte, posten.
    Gegeben ist folgende Klasse :

    class MScoreCounter
    {
    public:
    
        // Singleton
        static MScoreCounter& GetInstance() 
        {       
            static MScoreCounter Instance;
            return Instance;
        }
    
        void  IncScore(const MEnemy* p)
        {
            m_LastScore = p->GetPoints();
            m_Score += m_LastScore;    
        }
    
        int   GetScore() const 
        {
            return m_Score;
        }
    
        int   GetLastScore() const
        {
            return m_LastScore;
        }
    
    private:
    
        int   m_Score;
    
        int   m_LastScore;    // Die Höhe der zuletzt addierten Punkte
    
    private:
        MScoreCounter() : m_Score(0),m_LastScore(0) {}
        MScoreCounter(const MScoreCounter&);
    
        MScoreCounter& operator=(const MScoreCounter&);
    };
    

    sieht doch alles korrekt aus.
    Es lief auch alles prima, solange ich im Debug Modus ( MSVC6 ) compilierte. Und am Ende meines Projektes compilierte ich alles nochmal im Release, spielte eine Probepartie und erlebte eine Überraschung. In der Klasse Game konnte ich die Punkte immernoch perfekt auslesen, aber als ich diese Klasse dann zerstörte und meine HighScrore Klasse aufrief, welche über GetPoints die Punkte ausliess, bekamm ich nur noch Müll. Abhilfe schaffte es alles in eine cpp Datei zu packen, also auf inline zu verzichten.
    Ich weiss nicht genau woran es lag, aber ich denke das statische Variablen und inline sich beissen.
    Nun verwende ich kaum noch inline und was ich damit sagen will weiss ich auch nicht, aber ich musste es einfach mal posten 🙂
    Aber vielleicht bin ich auch nur der einzige Trottel mit solch einem Fehler, mein Visual scheint sowieso kaputt zu sein 🙂



  • Original erstellt von Real_PsychoDAD:
    **Hi,
    Ich weiss nicht genau woran es lag, aber ich denke das statische Variablen und inline sich beissen.
    **

    So isses. Abgesehen davon ist inline aber nicht böse.



  • Original erstellt von Lars Skiba:
    Mir gefällt der 3. Weg am besten, den nehm ich 🙂

    Hmm. Für die Übersichtlichkeit bringt er nix.
    Aber, mal sehen, man könnte sowas versuchen, daß nicht die *.h die *.inl inkludiert, sondern Umgekehrt!
    Und wer nur den Typ ohne Größe braucht, macht ne Forward-Deklaration, wer den Typ mit Größe braucht, macht #include "bla.h" und wer nen voll funktionierenden Typ braucht, macht #include "bla.inl".
    Hat sowas schonmal jemand versucht? Wir ging es aus?
    edit: statt .h lieber _fwd.h und statt .inl lieber .h, ist aber erstmal egal, mir gehts mal nur um die Senkung der Abhängigkeiten.

    [ Dieser Beitrag wurde am 27.06.2002 um 19:42 Uhr von volkard editiert. ]



  • ich mach sowas in die Richtung, wegen des vorkompilierten Headern beim C++Builder. Wenn ich da nämlich inline-Funktionen hab, krieg ich ne Warnung "Code im Header" und es werden keine vorkompilierten Header erzeugt.

    Ich machs eigentlich aber nicht wegen inline-Funktionen (solche mach ich inzwischen nicht mehr), sondern bei spezialisierten Template-Funktionen/Klassen. Weil man das ja auch im Header machen muss.


Anmelden zum Antworten