Probleme mit const_reverse_iterator



  • Guten Abend!

    Man betrachte folgenden Code:

    #include <iostream>
    #include <vector>
    
    int main()
    {
      const char chars[] = "abcdefghijklmnopqrstuvwxyz";
    
      std::vector<char> alphabet(&chars[0], &chars[26]);
    
      // Alphabet rueckwaerts ausgeben 
      typedef std::vector<char>::const_reverse_iterator rIT;
      for (rIT rit = alphabet.rbegin(); rit != alphabet.rend(); ++rit)
        std::cout << *rit;
    
      std::cout << '\n';
    }
    

    Müsste eigentlich funktionieren oder? Der gcc jedoch sagt:

    problem.cpp: In function `int main()':
    problem.cpp:11: error: no match for 'operator!=' in 'rit != std::vector<_Tp,
    _Alloc>::rend() [with _Tp = char, _Alloc = std::allocator<char>]()'

    Falls man jedoch statt dem konstanten Reverse-Iterator den normalen
    verwendet:

    typedef std::vector<char>::reverse_iterator rIT;
    

    gibt es keine Probleme!
    (Danke nochmal an ShadeOfMine, der mir im Channel diesen Tipp gegeben hat.)

    Doch warum ist das so?

    gruß,
    walker



  • Jep, MSVC++6.0 + STL4.6.2 sagt hierzu:

    h:\gemeinsames\tests\test\main.cpp(12) : error C2440: 'initializing' : 'class _STL::reverse_iterator<char *,char,char &,char *,int>' kann nicht in 'class _STL::reverse_iterator<char const *,char,char const &,char const *,int>' konvertiert werden
            Quelltyp konnte von keinem Konstruktor angenommen werden, oder die Ueberladungsaufloesung des Konstruktors ist mehrdeutig
    

    das Problem liegt bei der Initialitisil... bei:
    rIT rit = alphabet.rbegin();
    Es geht aber, wenn der vector konstant ist:

    #include <iostream>
    #include <vector>
    
    int main()
    {
      const char chars[] = "abcdefghijklmnopqrstuvwxyz";
    
      const std::vector<char> alphabet(&chars[0], &chars[26]); // HIER
    
      // Alphabet rueckwaerts ausgeben
      typedef std::vector<char>::const_reverse_iterator rIT;
      for (rIT rit = alphabet.rbegin(); rit != alphabet.rend(); ++rit)
        std::cout << *rit;
    
      std::cout << '\n';
    }
    

    MfG MAV



  • Doch warum ist das so?

    rend() liefert für ein nicht konstantes Objekt einen reverse_iterator. Für ein konstantes Objekt einen const_reverse_operator. Du hast hier ein nicht konstanten Vektor. Damit hast du auf der linken Seite deiner Ungleichung einen const_reverse_iterator und auf der rechten Seite einen normalen reverse_iterator.
    Nun gibt es dummerweise aber keinen operator!= der diese Kombination von Argumenten verarbeiten kann.

    Du musst natürlich nicht gleich einen konstanten Vektor nehmen. Ein simpler const_cast sollte auch reichen:

    #include <iostream>
    #include <vector>
    
    int main()
    {
      const char chars[] = "abcdefghijklmnopqrstuvwxyz";
    
      std::vector<char> alphabet(&chars[0], &chars[26]);
    
      // Alphabet rueckwaerts ausgeben 
      typedef std::vector<char>::const_reverse_iterator rIT;
      for (rIT rit = alphabet.rbegin(); rit != const_cast<const std::vector<char>& >(alphabet).rend(); ++rit)
        std::cout << *rit;
    
      std::cout << '\n';
    }
    


  • Was ich jetzt erst sehe:
    Dein Code produziert undefiniertes Verhalten. Und zwar hier:

    std::vector<char> alphabet(&chars[0], &chars[26]);

    Da der operator[] zu einer Dereferenzierung führt und 26 außerhalb deines Arrays liegt, ist &chars[26] undefiniert.

    Du willst ja eigentlich nur einen end-Iterator. Korrekt wäre das:

    std::vector<char> alphabet(chars, chars + 26);
    


  • HumeSikkins schrieb:

    Was ich jetzt erst sehe:
    Dein Code produziert undefiniertes Verhalten. Und zwar hier:

    std::vector<char> alphabet(&chars[0], &chars[26]);

    Da der operator[] zu einer Dereferenzierung führt und 26 außerhalb deines Arrays liegt, ist &chars[26] undefiniert.

    Wieso?
    chars[26] ist doch das 0 Byte...

    Natürlich würde ich auch chars+26 verwenden...



  • Shade Of Mine schrieb:

    HumeSikkins schrieb:

    Was ich jetzt erst sehe:
    Dein Code produziert undefiniertes Verhalten. Und zwar hier:

    std::vector<char> alphabet(&chars[0], &chars[26]);

    Da der operator[] zu einer Dereferenzierung führt und 26 außerhalb deines Arrays liegt, ist &chars[26] undefiniert.

    Wieso?
    chars[26] ist doch das 0 Byte...

    Das ist ein Argument, das ich nicht widerlegen kann 😃
    Hast natürlich recht.


Anmelden zum Antworten