2016-06-10 37 views
1

I const_cast wurde unter Verwendung von Elementen innerhalb eines initializer_list zu verändern, wie unten:C++ 11 modifizierende Elemente in initializer_list mit Zeiger verursacht SIGSEGV, warum?

#include <initializer_list> 
int main() 
{ 
    auto a1={1,2,3}; 
    auto a2=a1;//copy or reference? 
    for(auto& e:a1) 
    { 
     int*p=const_cast<int*>(&e); 
     ++(*p); 
    } 
    for(auto& e:a2) 
     cout<<e; 
    return 0; 
} 

Leider, wenn ++ tut (* p) das g ++ 4.9.2 kompilierten Programm wirft SIGSEGV. Das Problem tritt nicht in VC auf.

Warum ist das, ist mein Programm mit unsicheren Operationen? Bitte helfen Sie, danke.

+1

'auto a2 = a1;' wird nie eine Referenz sein, nur eine Kopie. Wenn Sie eine Referenz haben wollen, müssen Sie explizit wie in 'auto & a2 = a1;' –

+3

sein. Sie haben eine 'const_cast' dann eine Mutation auf der Castee durchgeführt, und Sie wollen wissen, ob Ihr Programm" irgendwelche unsicheren Operationen "hat? –

Antwort

3

Als I mentioned zu Ihrer vorherigen Frage, das zugrunde liegende Array für eine initializer_list<T> besteht aus const Objekte. Das Ändern der deklarierten Objekte const ist undefiniertes Verhalten. Von [dcl.type.cv]:

Abgesehen davon, dass jede Klasse Mitglied wandelbar erklärt (7.1.1) modifiziert werden kann, jeder Versuch, ein const Objekt während seiner Lebenszeit (3,8) führt zu undefiniertem Verhalten zu ändern.

Eine mögliche Instanziierung von undefiniertem Verhalten ist SIGSEV, was Sie von gcc sehen. Eine andere mögliche Instanziierung ist die Code-Arbeit, die Sie in VC sehen. Tu es einfach nicht.

5

Es ist undefiniertes Verhalten, Daten zu ändern, die ursprünglich als const deklariert wurden, und der Inhalt einer Initialisierungsliste ist immer const.

In diesem Fall scheint es, dass der Inhalt der Liste in einer schreibgeschützten Seite oder einem solchen gespeichert wird, und Sie erhalten einen Laufzeitfehler. Sie haben Glück: mit undefiniertem Verhalten alles kann passieren.

Ein weiteres klassisches Beispiel für undefiniertes Verhalten beim Schreiben auf const ist, wenn Sie etwas in einer Zeile ändern, und in der nächsten Zeile lesen Sie es und die Änderungen werden nicht angezeigt. Dies geschieht, weil der Compiler annehmen kann, dass alle const-deklarierten (nicht referenzierten) Daten nicht ändern, so dass es seinen Code optimieren kann, um davon auszugehen, dass der Anfangswert der Wert ist, den es immer hat.

Andere Möglichkeiten, die tatsächlich tun Compiler ist der Compiler bemerken Sie auf einem Zweig nicht definiertes Verhalten tun, Argumentation, dass die Verzweigung nicht logisch genommen werden, abzuleiten, dass die Bedingung der Verzweigung eingeben muss die andere Einstellung sein, und die Beseitigung eine Verzweigung ganz (und/oder in eine Verzweigung gehen, deren Vorbedingungen durch die obige Logik bewiesen sind). Undefiniertes Verhalten kann Zeitreisen verursachen.

Ihre Festplatte könnte formatiert werden, der Computer könnte explodieren, E-Mail Ihre Web-Geschichte an Ihre Eltern: ein Compiler ist frei, um den Code zu machen, an irgendeinem Punkt, aus irgendeinem Grund.

Machen Sie kein undefiniertes Verhalten.