2016-07-22 8 views
0

Ich bin etwas mit const_iterators verwirrt. Zum Beispiel wollen wir die Funktion betrachten:Warum Compiler ermöglicht einen Verweis auf Iterator in Funktion senden, die einen Verweis auf Const Iterator nimmt?

void functionForConstIterator(std::list<int> const& list, std::list<int>::const_iterator& const_iter) 
{ 
    const_iter = list.begin(); 
} 

Jetzt kann ich schreiben:

void main() 
{ 
    std::list<int> myList = {1, 2, 3, 4, 5}; 
    std::list<int> const& listRef = myList; 
    std::list<int>::iterator iter; 

    functionForConstIterator(listRef, iter); 
    *iter = 7; 

    for (auto it = myList.begin(); it != myList.end(); ++it) 
     std::cout << *it << " "; 
} 

Der Ausgang ist {7, 2, 3, 4, 5}. Warum? Wenn ich einen Const-Verweis auf einen Container bekomme, muss ich ihn nicht ändern. Dies ist Visual Studio 2015-Compiler.

+0

Wenn ein Funktionsparameter ist eine konstante Referenz, die nur bedeutet, dass die Funktion, die sie nicht ändern können. Es wird nicht dazu führen, außerhalb der Funktion const zu sein. – JETM

+0

[Ihr Code ist falsch] (http://coliru.stacked-crooked.com/a/1bc62e737a7e80f4) –

+0

Aber es bedeutet, dass wenn ich nur const Referenz habe, nicht den Container selbst, ich kann es immer ändern. –

Antwort

1

Die Microsoft STL list::iterator stammt von list::const_iterator. Aus diesem Grund können Sie ohne Probleme eine Referenz an Ihre iterator an die Funktion const_iterator übergeben.

Die Zuweisung innerhalb der Funktion ist also eine Slicing-Zuweisung, dies hat jedoch in diesem Fall keine besonderen Auswirkungen, da iterator keine virtuellen Funktionen hat und keine neuen Member einführt.

Damit haben Sie dank der Zuweisung const_iterator heimlich in einen iterator umgewandelt.

Edit: ich ein Connect Problem für diese erstellt haben:

https://connect.microsoft.com/VisualStudio/feedback/details/2962643

+0

Ist eine solche Implementierung durch den Standard verboten? –

+0

Ich glaube nicht, dass es technisch ist, da der Standard spezifiziert "dies kann nicht kompilieren" nur an sehr wenigen Stellen der Bibliothek, aber es ist sicherlich sehr schlechte Qualität der Umsetzung. –

2

Wenn ich einen Const-Verweis auf einen Container bekomme, sollte ich nicht in der Lage sein, es zu ändern.

Das stimmt. Sie erhalten jedoch keine konstante Referenz für einen Container. Trotz seines Namens ist const_iteratornicht a const aus der Sicht der Sprache. Der Name const soll den Programmierern anzeigen, dass Sie den Container nicht über diesen Iterator ändern können. Der Iterator selbst bleibt ein faires Ziel, das geändert werden muss.

Darüber hinaus ist der Iterator ein const_iterator nur innerhalb der Funktion. Außerhalb der Funktion, d. H. In main, ist es ein regulärer std::list<int>::iterator, der vor und nach dem Aufruf der Funktion vollständig änderbar bleibt.

+0

Aber es folgt, dass, wenn ich nur const Referenz habe, nicht den Container selbst, ich immer den Container wechseln kann. Was ist Sinn von const Referenzen in diesem Fall? –

+0

Die eigentliche Frage ist: Soll man einem nichtkonstanten Iterator direkt oder indirekt einen konstanten Iterator zuweisen und so den zugrunde liegenden Container modifizieren?Und die Antwort, IMO, sollte ** nein ** sein. – nonsensickle

+0

Um meine Aussage weiter zu verdeutlichen, sollte es nicht erlaubt sein, einen 'const_iterator' in einen geraden 'iterator' zu ändern, implizit oder indirekt. – nonsensickle