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.