Verständnisfrage std::vector



  • Hallo:

    Ich habe folgende Klasse (gekürzt):

    class foo{
      public:
        vector<int> getVector(){return myvector};
        void printVector(){
          for(vector<int>::iterator i = myvector.begin(); i != myvector.end(); i++)
            cout << *i << endl;
        }
      private:
        vector<int> myvector;
    };
    

    Folgendes rufe ich nun in meiner main auf (nehmen wir an, myvector wurde mit 3 und 2 initialisiert):

    int main()
    {
      foo myfoo;
      myfoo.printVector();
      vector<int> test = myfoo.getVector();
      for(vector<int>::iterator i = test.begin(); i != test.end(); i++)
        cout << *i << endl;
      vector<int> test2(myfoo.getVector());
      for(vector<int>::iterator i = test2.begin(); i != test2.end(); i++)
        cout << *i << endl;
      for(vector<int>::iterator i = myfoo.getVector().begin(); i != myfoo.getVector.end(); i++)
        cout << *i << endl;
      return 0;
    }
    

    Auf meiner Maschine ergibt sich folgendes Bild:
    3
    2
    3
    2
    3
    2
    40731442 (<= diese Zahl ist konstant!)
    2

    Wenn ich mehr Zahlen in den Vector stecke, stimmen diese überein - nur bei der vierten Version bleibt die erste Zahl konstant falsch, je nach Anzahl der im Vector enthaltenen Zahlen ändert sie sich jedoch. Was mache ich falsch? Warum kann ich den Vector anscheinend nicht so ausgeben wie in Schritt 4?


  • Mod

    myfoo.getVector().begin();
    

    Das ist ein Iterator auf eine temporäre Kopie. Die lebt nicht mehr, sobald der Initialisierungsaudruck in der for-Schleife verlassen wird. Alles danach ist undefiniertes Verhalten.

    Das liegt nicht direkt an vector, sondern an der Art und Weise, wie du dein getVector() geschrieben hast. Es wäre vielleicht besser, eine Referenz zurückzugeben. Das hat auch den Vorteil dir jede Menge unnötige Kopierkosten zu sparen.

    viele edits: Irgendwie hab ich es heute nicht so mit Rechtschreibung und ganzen Sätzen...



  • Schade, dass ich den Code noch korrigieren und vervollständigen muss, um ihn testen zu können.

    Ich möchte nochmal darauf hinweisen, dass ein entsprechender Debug-Modus sehr hilfreich sein kann:

    #include <vector>
    #include <iostream>
    
    using namespace std;
    
    class foo{
      public:
        foo() {
          myvector.push_back(2);
          myvector.push_back(3);
        }
        vector<int> getVector() {
          return myvector;
        }
        void printVector(){
          for(vector<int>::iterator i = myvector.begin(); i != myvector.end(); ++i)
            cout << *i << endl;
        }
      private:
        vector<int> myvector;
    };	
    
    int main(){
      foo myfoo;
      myfoo.printVector();
      vector<int> test = myfoo.getVector();
      for(vector<int>::iterator i = test.begin(); i != test.end(); ++i)
        cout << *i << endl;
      vector<int> test2(myfoo.getVector());
      for(vector<int>::iterator i = test2.begin(); i != test2.end(); ++i)
        cout << *i << endl;
      for(vector<int>::iterator i = myfoo.getVector().begin(); i != myfoo.getVector().end(); ++i)
        cout << *i << endl;
      return 0;
    }
    
    > g++ -D_GLIBCXX_DEBUG ohoh.cpp
    > a.exe
    
    2
    3
    2
    3
    2
    3
    
    This application has requested the Runtime to terminate it in an unusual way.
    Please contact the application's support team for more information.
    c:\mingw32\bin\../lib/gcc/mingw32/4.5.1/include/c++/debug/safe_iterator.h:464:
        error: attempt to compare a singular iterator to a past-the-end iterator    
        .
    
    Objects involved in the operation:
    iterator "lhs" @ 0x0028fdfc {
    type = N11__gnu_debug14_Safe_iteratorIN9__gnu_cxx17__normal_iteratorIPiNSt6__norm6vectorIiSaIiEEEEENSt7__debug6vectorIiS6_EEEE (mutable iterator);
      state = singular;
    }
    iterator "rhs" @ 0x0028fed0 {
    type = N11__gnu_debug14_Safe_iteratorIN9__gnu_cxx17__normal_iteratorIPiNSt6__norm6vectorIiSaIiEEEEENSt7__debug6vectorIiS6_EEEE (mutable iterator);
      state = past-the-end;
      references sequence with type `NSt7__debug6vectorIiSaIiEEE' @ 0x0028fed0
    }
    

    In Zeile 32 kracht es. i ist ein ungültiger Iterator und der wird mit einem anderen verglichen.

    Leute, nutzt sämtliche Debugmodi, die ihr kriegen könnt. Schaut in Eure Compiler-Doku rein.

    kk



  • Hallo und vielen Dank für eure Antworten; Mein Fehler leuchtet mir ein. Ich gebe jetzt eine Referenz auf const zurück und nutze cbegin/cend statt begin/end und es läuft!

    @KK: Den Debugger hab ich drüberlaufen lassen (gdb), der konnte mir nichts weiter sagen als dass eine Exception aufgetreten ist (cxa_throw())



  • begin/end ist überladen. Du kannst auch ruhig weiter begin/end verwenden. cbegin/cend gibt es nur ab C++2011. Und dort ist es praktisch, wenn du einen nicht-const-container hast, aber trotzdem const_iteratoren haben möchtest.

    Bzgl Debug-Modi hast Du mich vielleicht missverstanden. -D_GLIBCXX_DEBUG aktiviert den Debugmodus der Standardbibliothek. Das hat mit dem GDB wenig zu tun.


Anmelden zum Antworten