Dynamisches String Array (Vektor)



  • Judden Dach. Ich möchte mich kurz fassen. Ich habe ein Programm das eine Eingabe von mehreren Strings abspeichern muss. Diese Strings können in der Anzahl zwischen 1 und 500 liegen. Ich habe schon bei meiner Suche einiges über Vektoren gehört jedoch verstehe ich die Syntax und die Verwendung noch nicht so ganz. Kann mir hier einer mal einen kleinen Start geben?
    Vielleicht ein Beispiel + kurze Erläuterung bitte.

    Gruß



  • Hallo,

    eigentlich ganz einfach.

    std::vector<std::string> mystrings; // Ein leerer vector, in dem man strings speichern kann
    
    mystrings.push_back("Hello, World!"); // Wir fügen den string am Ende ein
    mystrings.push_back("Goodbye!"); // Wir fügen einen weiteren string ein
    
    std::cout << mystrings[0] << '\n'; // Zugriff wie bei einem Array
    


  • Eine kurze Verständnisfrage zum Aufbau eines Vektors im Arbeitsspeicher.
    Soweit ich weiß sind Arrays doch nichts anderes als im hintereinander liegende Bytes im Arbeitsspeicher. Nach meinem Wissen kann man die Größe eines einmal deklarierten Arrays nicht mehr verändern (zumindest nicht ohne Umwege). Wie kann dann ein Array erzeugt werden das eine variable Größe hat und trotzdem im Speicher zusammenhängt? Oder sehe ich da etwas falsch?



  • Der vector holt sich am Anfang einen Speicherbereich, sagen wir für 8 Elemente. Wenn du ein 9tes einfügst, holt er sich einen neuen Speicherbereich, der im Normalfall 1.5 bis 2 mal so groß ist wie der alte und kopiert alle Elemente rüber. Unter C++0x werden Elemente gemovt, wenn move-Semantik vom gespeicherten Typen unterstützt wird.


  • Mod

    Falls du die (nur in Extremfällen berechtigte) Sorge hast, dass die Kopieraktionen beim Vergrößern zu teuer sind, kannst du auch mit reserve angeben wie viele Elemente du später einmal einfügen möchtest.

    Eine vollstandige Referenz des vectors findest du hier:
    http://www.cplusplus.com/reference/stl/vector/
    Wie du siehst, kann der eine ganze Menge. Die meiner Erfahrung nach in der Praxis am häufigsten genutzten Funktionen (die du dir mal angucken solltest) sind:
    - Die verschiedenen Konstruktoren
    - begin, end, size
    - operator []
    - push_back
    Oftmals auch:
    - assign, back und resize
    Der Rest ist tendenziell eher obskur. Wenn man z.B. in der Mitte was mit insert/erase einfügen/löschen muss, dann hat man oft den falschen Container gewählt. Oder clear wird oft von Anfängern benutzt, die glauben, sie müssten den vector irgendwie freigeben.

    Und guck dir auch mal die algorithms und numeric an, die kann man wunderbar auf vectoren (und konventionelle Arrays auch) anwenden.

    Der std::string funktioniert übrigens in der Regel auch ähnlich wie ein vector<char>.



  • Soweit ich das mitbekommen habe, ist ein Vektor nichts anderes als "stinknormales" Array, was durch die Einbettung in eine Klasse mehr Funktionalität bietet.

    Wenn Du also einen Vektor richtig verstehen willst (und nicht nur anwenden), könntest Du versuchen, eine Klasse mit entsprechenden Funktionen auf der Basis eines Arrays selber zu programmieren.

    Schauen, wie sowas geht, kannst du bei: http://www.tbi.univie.ac.at/~pmg/tutorials/tmp/vcppk/html/die_klasse_stackasvector.html



  • Gehard schrieb:

    Judden Dach.

    Grüß Gott!

    Ich möchte mich kurz fassen. Ich habe ein Programm das eine Eingabe von mehreren Strings abspeichern muss. Diese Strings können in der Anzahl zwischen 1 und 500 liegen. Ich habe schon bei meiner Suche einiges über Vektoren gehört jedoch verstehe ich die Syntax und die Verwendung noch nicht so ganz. Kann mir hier einer mal einen kleinen Start geben?
    Vielleicht ein Beispiel + kurze Erläuterung bitte.

    Gruß

    Nimm ein Buch und lies dir das Kapitel über Pointer durch.



  • 314159265358979 schrieb:

    Der vector holt sich am Anfang einen Speicherbereich, sagen wir für 8 Elemente. Wenn du ein 9tes einfügst, holt er sich einen neuen Speicherbereich, der im Normalfall 1.5 bis 2 mal so groß ist wie der alte und kopiert alle Elemente rüber. Unter C++0x werden Elemente gemovt, wenn move-Semantik vom gespeicherten Typen unterstützt wird.

    Ist das wirklich so?
    Dachte, daß der wesentliche Vorteil eines Vektors darin besteht, mit "new" dynamisch Speicher vom sogenannten "Heap" anzufordern, so daß die alten Elemente nicht nochmal kopiert werden müssen.



  • Deshalb kann man dem vector mit reserve() sagen, wie viele Elemente man erwartet - um unnötiges Kopieren zu vermeiden.



  • 314159265358979 schrieb:

    Unter C++0x werden Elemente gemovt, wenn move-Semantik vom gespeicherten Typen unterstützt wird.

    Das ist aber nicht immer sicher. Was ist, wenn der move-Konstruktor eine exception schmeist? Das funktioniert nur, wenn es für den move-Konstruktor eine starke exception garantie gibt. (anbei: Ist für c++0x sowas wie is_nothrow_move_constructible<T> geplant bzw. schon umgesetzt? Was in dem Zusammenhang fast noch interessanter wäre, ist sowas wie is_mem_movable, das man selber spezialisieren kann, um zu zeigen, dass das Objekt per memcpy gemoved werden darf. Ein string, der als einziger Besitzer eines char arrays irgendwo im Speicher implementiert ist, wäre zum Beispiel ein Kandidat für sowas.)



  • redrew99 schrieb:

    314159265358979 schrieb:

    Der vector holt sich am Anfang einen Speicherbereich, sagen wir für 8 Elemente. Wenn du ein 9tes einfügst, holt er sich einen neuen Speicherbereich, der im Normalfall 1.5 bis 2 mal so groß ist wie der alte und kopiert alle Elemente rüber. Unter C++0x werden Elemente gemovt, wenn move-Semantik vom gespeicherten Typen unterstützt wird.

    Ist das wirklich so?
    Dachte, daß der wesentliche Vorteil eines Vektors darin besteht, mit "new" dynamisch Speicher vom sogenannten "Heap" anzufordern, so daß die alten Elemente nicht nochmal kopiert werden müssen.

    Da dachtest du falsch.
    std::vector muss definitiv umkopieren (bzw. "ummoven").



  • GorbGorb schrieb:

    314159265358979 schrieb:

    Unter C++0x werden Elemente gemovt, wenn move-Semantik vom gespeicherten Typen unterstützt wird.

    Das ist aber nicht immer sicher. Was ist, wenn der move-Konstruktor eine exception schmeist?

    Dann wird er nicht verwendet.
    Dazu gibt es std::is_nothrow_move_constructible<T> und std::move_if_noexcept .



  • Zu Move-Semantik und Exceptionsicherheit gabs übrigens gerade erst eine kurze Diskussion.



  • redrew99 schrieb:

    Soweit ich das mitbekommen habe, ist ein Vektor nichts anderes als "stinknormales" Array, was durch die Einbettung in eine Klasse mehr Funktionalität bietet.

    Da liegst du zumindest teilweise falsch, die Entsprechung eines C Arrays entspricht als Klasse im wesentlichen std::tr1::array, der Vektor kann mehr (wie z.B. das umkopieren bei Bedarf, was ein normales Array nicht kann...).



  • hustbaer schrieb:

    Dann wird er nicht verwendet.
    Dazu gibt es std::is_nothrow_move_constructible<T> und std::move_if_noexcept .

    Also ist das im neuen Standard mit dabei? Mein gcc kennts nämlich nocht nicht...

    asc schrieb:

    redrew99 schrieb:

    Soweit ich das mitbekommen habe, ist ein Vektor nichts anderes als "stinknormales" Array, was durch die Einbettung in eine Klasse mehr Funktionalität bietet.

    Da liegst du zumindest teilweise falsch, die Entsprechung eines C Arrays entspricht als Klasse im wesentlichen std::tr1::array, der Vektor kann mehr (wie z.B. das umkopieren bei Bedarf, was ein normales Array nicht kann...).

    Ich denke er meinte eher, dass der vector intern ein normales array verwendet.



  • GorbGorb schrieb:

    hustbaer schrieb:

    Dann wird er nicht verwendet.
    Dazu gibt es std::is_nothrow_move_constructible<T> und std::move_if_noexcept .

    Also ist das im neuen Standard mit dabei?

    Ja. Falls das entsprechende Objekt kopierbar ist und der move-ctor eine Ausnahme schmeißen könnte, liefert move_if_noexcept eine "Lvalue-Referenz auf const".

    Wenn T nicht kopierbar ist und einen potentiell schmeißenden Move-Ctor hat, dann hat der vector keine andere Wahl, darauf zu hoffen, dass beim Vergrößern alles gut geht. Wenn in dem Fall wirklich eine Ausnahme fliegt, ist der Zustand des Vektors unspezifiziert.

    Also, Klassen, die nur "movable" sind, sollten dann wirklich keine Ausnahme im move-ctor schmeißen.



  • GorbGorb schrieb:

    Ich denke er meinte eher, dass der vector intern ein normales array verwendet.

    Ja, genau.


Anmelden zum Antworten