Frage zu Klassen und member Funktionen



  • Hi, in beiden Lehrbüchern, die ich im moment durchlese wird oft davon gesprochen, daß der direkte Zugriff auf Variablen viel weniger Aufwand bedeutet als der Zugriff auf Variablen über eine Funktion(weil wegen irgendwas mit pushen)Warum wird das dann so häufig, zumindest in meinen Büchern, in Klassen anders gehandhabt, daß fast ausschliesslich über Funktionen Variablen bearbeitet werden.
    Wenn doch nur ich mein Programm verstehen muss und ich für niemanden anders ein Interface erstellen möchte, ist es dann nicht viel logischer und effizienter direkt mit Variablen zu arbeiten? Man spart Funktionen und ne menge Code. Warum also nicht die Variable public machen und alles in einen namespace oder so. ein einfaches beispiel zum verstehen was ich meine:

    namespace nstest {
    class test {
       public:
       int i;
    
       int get() const { return i; }
       void set(int ii) { i = ii; }
               };
    };
    //in main
    nstest::test a;
    std::cout << a.i;
    a.i = 10;
    
    ///////////////////////////////////////
    //anstelle   
    class test {
        int i;
        public:
       int get() const { return i; }
       void set(int ii) { i = ii; }
    };
    
    //in main
    test a;
    std::cout << a.get();
    a.set(10);
    


  • oh da ist mir ein fehler passiert. im oberen teil des code beispiels gehören die beiden funktionen get() und set(int) nicht dazu, also im namespace.



  • Beginner13 schrieb:

    Hi, in beiden Lehrbüchern, die ich im moment durchlese wird oft davon gesprochen, daß der direkte Zugriff auf Variablen viel weniger Aufwand bedeutet als der Zugriff auf Variablen über eine Funktion(weil wegen irgendwas mit pushen)Warum wird das dann so häufig, zumindest in meinen Büchern, in Klassen anders gehandhabt, daß fast ausschliesslich über Funktionen Variablen bearbeitet werden.
    Wenn doch nur ich mein Programm verstehen muss und ich für niemanden anders ein Interface erstellen möchte, ist es dann nicht viel logischer und effizienter direkt mit Variablen zu arbeiten? Man spart Funktionen und ne menge Code. Warum also nicht die Variable public machen und alles in einen namespace oder so. ein einfaches beispiel zum verstehen was ich meine:

    Das hatten wir schon sicherlich einige Tausend Male hier im Forum. getter und setter sind flexibler und der Overhead ist bei einem ordentlichen Compiler und Inline-Funktionen genau gleich 0.



  • Du wirfst damit das Prinzip der Datenkapselung über den Haufen.

    BTW: Wolltest du das wirklich, so könntest du auch struct's verwenden, denn in ihnen ist standardmäßig alles public.

    Greetz, Swordfish



  • ah ok danke. dann nur noch eine frage:

    //in main
    test a[100];
    for(i=0;i<100;++i)
        a[i].set(i);
    
    //wenn set(int) inline wäre, ist das dann zu 100 % derselbe aufwand im Code wie:
    test a[100];
    for(i=0;i<100;++i)
         a[i].i = i;
    
    //?
    

    kenn mich noch richtig aus 😞



  • Kommt drauf an wie set implementiert ist und welchen Compiler du verwendest. inline zwingt letzteren nicht, es ist eine Empfehlung. Wenn er diese annimmt und set als einfache Zuweisung implementiert ist, dann ja.



  • habe nochmal getestet, und push wird bei der inline funktion immer noch verwendet

    test p[100];
        for(int i = 0;i<100;++i)
    00411ECE  mov         dword ptr [i],0 
    00411ED8  jmp         main+39h (411EE9h) 
    00411EDA  mov         eax,dword ptr [i] 
    00411EE0  add         eax,1 
    00411EE3  mov         dword ptr [i],eax 
    00411EE9  cmp         dword ptr [i],64h 
    std::basic_ostream<char,std::char_traits<char> >::sentry::~sentry:
    00411EF0  jge         main+5Dh (411F0Dh) 
    
    		p[i].set(i); ;ist inline gesetzt
    
    00411EF2  mov         eax,dword ptr [i] 
    00411EF8  push        eax  
    00411EF9  mov         ecx,dword ptr [i] 
    00411EFF  lea         ecx,p[ecx*4] 
    00411F06  call        test::set (411285h) 
    00411F0B  jmp         main+2Ah (411EDAh) 
    
             ;test ohne Funktion
    
    	test p2[100];
    	for(int i = 0;i<100;++i)
    00411F0D  mov         dword ptr [i],0 
    00411F17  jmp         main+78h (411F28h) 
    00411F19  mov         eax,dword ptr [i] 
    00411F1F  add         eax,1 
    00411F22  mov         dword ptr [i],eax 
    00411F28  cmp         dword ptr [i],64h 
    00411F2F  jge         main+96h (411F46h) 
    
    		p[i].i = i;
    00411F31  mov         eax,dword ptr [i] 
    00411F37  mov         ecx,dword ptr [i] 
    00411F3D  mov         dword ptr p[eax*4],ecx 
    00411F44  jmp         main+69h (411F19h) 
    
    }
    

    wird hier mein inline gar nicht verwendet, weil der compiler so entschieden hat? inwiefern würde dann hier mehr code bei inline schneller oder langsamer als Funktionsaufrufe sein?



  • Hallo

    Ja inline ist nur eine Empfehlung für den Compiler (siehe auch den Magazinartikel hier im Forum). Desweiteren kann auch nur geinlined werden, wenn die komplette Implementation der zu inlinenden Funktion bekannt ist, nicht nur die Definition.

    Allerdings stellt sich die Frage, ob du wirklich an solchen Sachen mit der Optimierung anfangen solltest und ob die Datenkapselung den eventuellen minimalen Leistungsverlust nicht wert ist.

    bis bald
    akari



  • akari schrieb:

    Hallo

    Ja inline ist nur eine Empfehlung für den Compiler (siehe auch den Magazinartikel hier im Forum). Desweiteren kann auch nur geinlined werden, wenn die komplette Implementation der zu inlinenden Funktion bekannt ist, nicht nur die Definition.

    Allerdings stellt sich die Frage, ob du wirklich an solchen Sachen mit der Optimierung anfangen solltest und ob die Datenkapselung den eventuellen minimalen Leistungsverlust nicht wert ist.

    bis bald
    akari

    DAnke akari, ist das denn eine komplette implementation, die zu einem inline ausreicht?

    void set(int ii) { i = ii; }
    

    laut buch ist so eine funktion in einer klasse automatisch inline, stimmt das?

    sehr kurze funktion und der compiler scheint kein inline daraus zu machen, vielleciht wegen der 100 schleifendurchläufe.



  • Sowas sollte inline werden. Hast du im Release oder im Debug-Modus compiliert?



  • im debug modus. im release modus ist der asm code der inline funktion und des direkten Zugriffs gleich.

    danke 🙂



  • Beginner13 schrieb:

    im debug modus. im release modus ist der asm code der inline funktion und des direkten Zugriffs gleich.

    Dann liegt's wohl daran - im Debug-Modus schaltet der Compiler das Inlining ab, damit du deine Funktionen leichter debuggen kannst (der Debugger findet diese inline eingefügten Anweisungen sonst nicht wieder).



  • Du solltest auch bedenken das du anhand der getter und vorallem der setter mehr kontrolle über die Variablen hast.

    So kannst du zB in einem setter mit den Werten noch was rumspielen, berechnungen durchführen etc und dann deiner Variable zuweise. Zudem kannst du auch noch Fehlerkontrollen einbauen, was du alles beim direkten Zugriff nicht hast.


Log in to reply