String einlesen lassen (Klassen)



  • @mmm_1482_

    oder du machst sowas:

    string str;
    
    cin >> str;
    a.setName(str);
    


  • @Wade1234 perfekt das hat funktioniert! Vielen dank 🙂



  • @mmm_1482_ im hinblick auf oop ist das natürlich vorbildlich, geschwindigkeitsmäßig wird da aber wieder kopiert und alles ist langsam.🙄



  • @Wade1234 ja ich weiß.. nur müssen wir das für die Prüfung leider drauf haben 😃



  • @mmm_1482_ achso. ja also generell kannst du dir merken, dass du für jede popelige variable eine solche set-methode erstellen darfst, die dann den übergebenen wert kopiert. dadurch ist das dann alles schön abgesichert, aber gängige computerspiele laufen dann entsprechend langsam.🙄



  • @Wade1234 sagte in String einlesen lassen (Klassen):

    @mmm_1482_ achso. ja also generell kannst du dir merken, dass du für jede popelige variable eine solche set-methode erstellen darfst, die dann den übergebenen wert kopiert. dadurch ist das dann alles schön abgesichert, aber gängige computerspiele laufen dann entsprechend langsam.🙄

    Ordentlich implementiert sind Getter/Setter unter Optimierungen nicht lansamer als direkter Zugriff auf die Variablen (const&-Getter und Setter, die unnötige Kopien vermeiden, z.B. by value-Parameter + Move).

    Was aber definitiv stimmt, ist dass sie ein ziemlicher Schlepp zu implementieren sind und den Code mit jeder Menge Boilerplate aufblähen. Daher bin ich auch kein Fan davon.

    Sie haben aber nicht von der Hand zu weisende Vorteile: Ein einziges Interface um von außen auf Instanzattribute zuzugreifen, an das man bei Bedarf noch ein Stück zusätzlichen Code hängen kann.

    Manchmal wünsche ich mir sowas wie C#-Properties auch für C++. Es wäre schon manchmal nützlich Member-Zugriffe mit zusätzlichem Code versehen zu können, ohne das Interface so verändern zu müssen, dass man sämtlichen Code anpassen muss. Andererseits kann man aber auch Klassen so bauen, dass den Anwender nicht zu interessieren braucht, was für Attribute die alle haben - nur was für eine Funktionalität sie exponieren.



  • @Wade1234 sagte in String einlesen lassen (Klassen):

    geschwindigkeitsmäßig wird da aber wieder kopiert und alles ist langsam. 🙄

    So ein Quatsch. 🙄



  • @Swordfish sagte in String einlesen lassen (Klassen):

    @Wade1234 sagte in String einlesen lassen (Klassen):

    geschwindigkeitsmäßig wird da aber wieder kopiert und alles ist langsam. 🙄

    So ein Quatsch. 🙄

    du wiederholst dich...... 😃



  • Wenn du Blödsinn schreibst, dass "gängige Computerspiele [...] dann entsprechend langsam [laufen]", dann spendiere ich @Swordfish sogar noch die Soße zum Quatsch 😉

    Tipp: schau dir auf godbolt an, was wirklich passiert. Und wenn es Unterschiede gibt, beweise mit einem Profiler, dass das wirklich die Ursache ist.



  • ja da wird dann operator= aufgerufen, welches dann den inhalt kopiert.



  • @Wade1234 tu was @wob gesagt hat.



  • @Swordfish habe ich. operator= wird aufgerufen und laut http://www.cplusplus.com/reference/string/string/operator=/ wird der inhalt kopiert.



  • @Wade1234 sagte in String einlesen lassen (Klassen):

    @Swordfish habe ich. operator= wird aufgerufen und laut http://www.cplusplus.com/reference/string/string/operator=/ wird der inhalt kopiert.

    Ich verstehe nicht, was das mit dem Thema "getter und setter", die deiner Meinung nach alles langsam machen, zu tun haben sollte.



  • @wob sagte in String einlesen lassen (Klassen):

    @Wade1234 sagte in String einlesen lassen (Klassen):

    @Swordfish habe ich. operator= wird aufgerufen und laut http://www.cplusplus.com/reference/string/string/operator=/ wird der inhalt kopiert.

    Ich verstehe nicht, was das mit dem Thema "getter und setter", die deiner Meinung nach alles langsam machen, zu tun haben sollte.

    naja dass da im gegensatz zum direkten schreiben ein weiterer kopiervorgang stattfindet.



  • @Wade1234 Code? Link zu godbolt?



  • @Wade1234 sagte in String einlesen lassen (Klassen):

    naja dass da im gegensatz zum direkten schreiben ein weiterer kopiervorgang stattfindet.

    Aber nicht, so wie @Finnegan schon geschrieben hat, wenn man const & Getter und Setter benutzt.



  • @Swordfish sagte in String einlesen lassen (Klassen):

    @Wade1234 Code? Link zu godbolt?

    direktzugriff:

    // Type your code here, or load an example.
    #include <iostream>
    
    class MyClass
    {
        public:
        std::string mystring;
    };
    
    int main()
    {
        MyClass myclass;
    
        std::cin >> myclass.mystring;
    
        return 0;
    }
    
    MyClass::MyClass() [base object constructor]:
            push    rbp
            mov     rbp, rsp
            sub     rsp, 16
            mov     QWORD PTR [rbp-8], rdi
            mov     rax, QWORD PTR [rbp-8]
            mov     rdi, rax
            call    std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string() [complete object constructor]
            nop
            leave
            ret
    MyClass::~MyClass() [base object destructor]:
            push    rbp
            mov     rbp, rsp
            sub     rsp, 16
            mov     QWORD PTR [rbp-8], rdi
            mov     rax, QWORD PTR [rbp-8]
            mov     rdi, rax
            call    std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string() [complete object destructor]
            nop
            leave
            ret
    main:
            push    rbp
            mov     rbp, rsp
            push    rbx
            sub     rsp, 40
            lea     rax, [rbp-48]
            mov     rdi, rax
            call    MyClass::MyClass() [complete object constructor]
            lea     rax, [rbp-48]
            mov     rsi, rax
            mov     edi, OFFSET FLAT:_ZSt3cin
            call    std::basic_istream<char, std::char_traits<char> >& std::operator>><char, std::char_traits<char>, std::allocator<char> >(std::basic_istream<char, std::char_traits<char> >&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&)
            mov     ebx, 0
            lea     rax, [rbp-48]
            mov     rdi, rax
            call    MyClass::~MyClass() [complete object destructor]
            mov     eax, ebx
            jmp     .L7
            mov     rbx, rax
            lea     rax, [rbp-48]
            mov     rdi, rax
            call    MyClass::~MyClass() [complete object destructor]
            mov     rax, rbx
            mov     rdi, rax
            call    _Unwind_Resume
    .L7:
            add     rsp, 40
            pop     rbx
            pop     rbp
            ret
    __static_initialization_and_destruction_0(int, int):
            push    rbp
            mov     rbp, rsp
            sub     rsp, 16
            mov     DWORD PTR [rbp-4], edi
            mov     DWORD PTR [rbp-8], esi
            cmp     DWORD PTR [rbp-4], 1
            jne     .L10
            cmp     DWORD PTR [rbp-8], 65535
            jne     .L10
            mov     edi, OFFSET FLAT:_ZStL8__ioinit
            call    std::ios_base::Init::Init() [complete object constructor]
            mov     edx, OFFSET FLAT:__dso_handle
            mov     esi, OFFSET FLAT:_ZStL8__ioinit
            mov     edi, OFFSET FLAT:_ZNSt8ios_base4InitD1Ev
            call    __cxa_atexit
    .L10:
            nop
            leave
            ret
    _GLOBAL__sub_I_main:
            push    rbp
            mov     rbp, rsp
            mov     esi, 65535
            mov     edi, 1
            call    __static_initialization_and_destruction_0(int, int)
            pop     rbp
            ret
    

    zugriff über einfachen setter (nebenbei erwähnt fast doppelt so lang):

    // Type your code here, or load an example.
    #include <iostream>
    
    class MyClass
    {
        std::string mystring;
    
        public:
        void SetMystring(std::string str);
    };
    
    void MyClass::SetMystring(std::string str)
    {
        mystring = str;
    }
    
    int main()
    {
        MyClass myclass;
        std::string str;
    
        std::cin >> str;
    
        myclass.SetMystring(str);
    
        return 0;
    }
    
    MyClass::SetMystring(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >):
            push    rbp
            mov     rbp, rsp
            sub     rsp, 16
            mov     QWORD PTR [rbp-8], rdi
            mov     QWORD PTR [rbp-16], rsi
            mov     rax, QWORD PTR [rbp-8]
            mov     rdx, QWORD PTR [rbp-16]
            mov     rsi, rdx
            mov     rdi, rax
            call    std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::operator=(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)
            nop
            leave
            ret
    MyClass::MyClass() [base object constructor]:
            push    rbp
            mov     rbp, rsp
            sub     rsp, 16
            mov     QWORD PTR [rbp-8], rdi
            mov     rax, QWORD PTR [rbp-8]
            mov     rdi, rax
            call    std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string() [complete object constructor]
            nop
            leave
            ret
    MyClass::~MyClass() [base object destructor]:
            push    rbp
            mov     rbp, rsp
            sub     rsp, 16
            mov     QWORD PTR [rbp-8], rdi
            mov     rax, QWORD PTR [rbp-8]
            mov     rdi, rax
            call    std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string() [complete object destructor]
            nop
            leave
            ret
    main:
            push    rbp
            mov     rbp, rsp
            push    rbx
            sub     rsp, 104
            lea     rax, [rbp-80]
            mov     rdi, rax
            call    MyClass::MyClass() [complete object constructor]
            lea     rax, [rbp-112]
            mov     rdi, rax
            call    std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string() [complete object constructor]
            lea     rax, [rbp-112]
            mov     rsi, rax
            mov     edi, OFFSET FLAT:_ZSt3cin
            call    std::basic_istream<char, std::char_traits<char> >& std::operator>><char, std::char_traits<char>, std::allocator<char> >(std::basic_istream<char, std::char_traits<char> >&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&)
            lea     rdx, [rbp-112]
            lea     rax, [rbp-48]
            mov     rsi, rdx
            mov     rdi, rax
            call    std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)
            lea     rdx, [rbp-48]
            lea     rax, [rbp-80]
            mov     rsi, rdx
            mov     rdi, rax
            call    MyClass::SetMystring(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >)
            lea     rax, [rbp-48]
            mov     rdi, rax
            call    std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string() [complete object destructor]
            mov     ebx, 0
            lea     rax, [rbp-112]
            mov     rdi, rax
            call    std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string() [complete object destructor]
            lea     rax, [rbp-80]
            mov     rdi, rax
            call    MyClass::~MyClass() [complete object destructor]
            mov     eax, ebx
            jmp     .L10
            mov     rbx, rax
            lea     rax, [rbp-48]
            mov     rdi, rax
            call    std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string() [complete object destructor]
            jmp     .L7
            mov     rbx, rax
    .L7:
            lea     rax, [rbp-112]
            mov     rdi, rax
            call    std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string() [complete object destructor]
            lea     rax, [rbp-80]
            mov     rdi, rax
            call    MyClass::~MyClass() [complete object destructor]
            mov     rax, rbx
            mov     rdi, rax
            call    _Unwind_Resume
    .L10:
            add     rsp, 104
            pop     rbx
            pop     rbp
            ret
    __static_initialization_and_destruction_0(int, int):
            push    rbp
            mov     rbp, rsp
            sub     rsp, 16
            mov     DWORD PTR [rbp-4], edi
            mov     DWORD PTR [rbp-8], esi
            cmp     DWORD PTR [rbp-4], 1
            jne     .L13
            cmp     DWORD PTR [rbp-8], 65535
            jne     .L13
            mov     edi, OFFSET FLAT:_ZStL8__ioinit
            call    std::ios_base::Init::Init() [complete object constructor]
            mov     edx, OFFSET FLAT:__dso_handle
            mov     esi, OFFSET FLAT:_ZStL8__ioinit
            mov     edi, OFFSET FLAT:_ZNSt8ios_base4InitD1Ev
            call    __cxa_atexit
    .L13:
            nop
            leave
            ret
    _GLOBAL__sub_I_MyClass::SetMystring(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >):
            push    rbp
            mov     rbp, rsp
            mov     esi, 65535
            mov     edi, 1
            call    __static_initialization_and_destruction_0(int, int)
            pop     rbp
            ret
    

    setter mit referenz:

    // Type your code here, or load an example.
    #include <iostream>
    
    class MyClass
    {
        std::string mystring;
    
        public:
        void SetMystring(const std::string &str);
    };
    
    void MyClass::SetMystring(const std::string &str)
    {
        mystring = str;
    }
    
    int main()
    {
        MyClass myclass;
        std::string str;
    
        std::cin >> str;
    
        myclass.SetMystring(str);
    
        return 0;
    }
    
    MyClass::SetMystring(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&):
            push    rbp
            mov     rbp, rsp
            sub     rsp, 16
            mov     QWORD PTR [rbp-8], rdi
            mov     QWORD PTR [rbp-16], rsi
            mov     rax, QWORD PTR [rbp-8]
            mov     rdx, QWORD PTR [rbp-16]
            mov     rsi, rdx
            mov     rdi, rax
            call    std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::operator=(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)
            nop
            leave
            ret
    MyClass::MyClass() [base object constructor]:
            push    rbp
            mov     rbp, rsp
            sub     rsp, 16
            mov     QWORD PTR [rbp-8], rdi
            mov     rax, QWORD PTR [rbp-8]
            mov     rdi, rax
            call    std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string() [complete object constructor]
            nop
            leave
            ret
    MyClass::~MyClass() [base object destructor]:
            push    rbp
            mov     rbp, rsp
            sub     rsp, 16
            mov     QWORD PTR [rbp-8], rdi
            mov     rax, QWORD PTR [rbp-8]
            mov     rdi, rax
            call    std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string() [complete object destructor]
            nop
            leave
            ret
    main:
            push    rbp
            mov     rbp, rsp
            push    rbx
            sub     rsp, 72
            lea     rax, [rbp-48]
            mov     rdi, rax
            call    MyClass::MyClass() [complete object constructor]
            lea     rax, [rbp-80]
            mov     rdi, rax
            call    std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string() [complete object constructor]
            lea     rax, [rbp-80]
            mov     rsi, rax
            mov     edi, OFFSET FLAT:_ZSt3cin
            call    std::basic_istream<char, std::char_traits<char> >& std::operator>><char, std::char_traits<char>, std::allocator<char> >(std::basic_istream<char, std::char_traits<char> >&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&)
            lea     rdx, [rbp-80]
            lea     rax, [rbp-48]
            mov     rsi, rdx
            mov     rdi, rax
            call    MyClass::SetMystring(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)
            mov     ebx, 0
            lea     rax, [rbp-80]
            mov     rdi, rax
            call    std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string() [complete object destructor]
            lea     rax, [rbp-48]
            mov     rdi, rax
            call    MyClass::~MyClass() [complete object destructor]
            mov     eax, ebx
            jmp     .L8
            mov     rbx, rax
            lea     rax, [rbp-80]
            mov     rdi, rax
            call    std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string() [complete object destructor]
            lea     rax, [rbp-48]
            mov     rdi, rax
            call    MyClass::~MyClass() [complete object destructor]
            mov     rax, rbx
            mov     rdi, rax
            call    _Unwind_Resume
    .L8:
            add     rsp, 72
            pop     rbx
            pop     rbp
            ret
    __static_initialization_and_destruction_0(int, int):
            push    rbp
            mov     rbp, rsp
            sub     rsp, 16
            mov     DWORD PTR [rbp-4], edi
            mov     DWORD PTR [rbp-8], esi
            cmp     DWORD PTR [rbp-4], 1
            jne     .L11
            cmp     DWORD PTR [rbp-8], 65535
            jne     .L11
            mov     edi, OFFSET FLAT:_ZStL8__ioinit
            call    std::ios_base::Init::Init() [complete object constructor]
            mov     edx, OFFSET FLAT:__dso_handle
            mov     esi, OFFSET FLAT:_ZStL8__ioinit
            mov     edi, OFFSET FLAT:_ZNSt8ios_base4InitD1Ev
            call    __cxa_atexit
    .L11:
            nop
            leave
            ret
    _GLOBAL__sub_I_MyClass::SetMystring(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&):
            push    rbp
            mov     rbp, rsp
            mov     esi, 65535
            mov     edi, 1
            call    __static_initialization_and_destruction_0(int, int)
            pop     rbp
            ret
    

    der kopiervorgang findet übrigens in zeile 11 statt.



  • Mir scheint der Vergleich nicht ganz fair. @Wade1234 im Direktzugriff schreibst du direkt aus dem Stream in den entsprechenden String während du im Setter Fall einen weiteren String nimmst um die Eingabe zu verarbeiten.

    In der Regel wird man irgendwo her schon ein String haben, denn man ablegen will.
    Und ob man:

    void example(std::string str)
    {
       MyClass mclass;
       mclass.mystring = str;
    }
    

    hat, oder

    void example(std::string str)
    {
      MyClass mclass;
      mclass.setMystring(str);
    }
    

    macht bei korrekter Implementierung vom Setter keinen Unterschied.



  • @Schlangenmensch aber im ausgangspost ging es darum, dass der benutzer einen string eingibt und dieser in der klasse bzw. der instanz abgelegt werden muss.



  • @Wade1234
    Und beim nächsten mal braucht er die Klasse in einem anderen Zusammenhang und dann hat er den "Salat".

    Wenn es um aus einem Stream geht, könnte man auch so was machen:

    #include <iostream>
    class myClass
    {
    public:
    void fromStream(std::istream& str)
    {
      str >> myString;
    }
    private:
    std::string myString;
    };
    int main()
    {
        myClass myclass;
    
        myclass.fromStream(std::cin);
        return 0;
    }
    

Anmelden zum Antworten