Das in Ihrem
erstellte Objekt %Vor%ist ein temporäres Objekt, das in diesem Ausdruck nur lebendig ist ;
%Vor%ist ein Objekt, das für den gesamten Block aktiv ist.
Warum gibt der folgende Code "xxY" aus? Sollten lokale Variablen nicht im Rahmen der gesamten Funktion leben? Kann ich ein solches Verhalten verwenden oder wird dies in zukünftigen C ++ - Standards geändert?
Ich dachte, dass nach C ++ Standard 3.3.2 " Ein in einem Block deklarierter Name lokal für diesen Block ist. Sein potenzieller Umfang beginnt an seinem Deklarationspunkt und endet am Ende seiner deklarativen Region. "
%Vor% Aufgrund der Antworten kann ich annehmen, dass MyClass(12345);
der Ausdruck (und der Gültigkeitsbereich) ist. Das ist sinnvoll. Also erwarte ich, dass der folgende Code immer "xYx" ausgibt:
Und es ist erlaubt, einen solchen Ersatz zu machen:
%Vor%Sie haben den Standard korrekt zitiert. Lassen Sie mich betonen:
Ein Name deklariert in einem Block ist lokal für diesen Block. Sein potenzieller Geltungsbereich beginnt am Ort der Erklärung und endet am Ende seiner deklarativen Region.
Sie haben tatsächlich keinen Namen angegeben. Ihre Zeile
%Vor% enthält nicht einmal eine Deklaration ! Es enthält einen Ausdruck, der eine Instanz von MyClass erstellt, den Ausdruck berechnet (aber in diesem speziellen Fall gibt es nichts zu berechnen), und wirft sein Ergebnis auf void
und zerstört die dort erstellten Objekte.
Eine weniger verwirrende Sache würde wie
klingen %Vor% Du hast es viele Male gesehen und weißt, wie es funktioniert, nicht wahr?Sie erstellen ein Objekt tatsächlich, ohne es in seinem Umfang zu belassen. Daher wird es direkt nach der Erstellung zerstört. Daher das Verhalten, das Sie erleben.
Sie können nicht auf das erstellte Objekt zugreifen, also warum sollte der Compiler es beibehalten?
Um Ihre anderen Fragen zu beantworten. Das folgende ist der Aufruf des Komma-Operators. Es erstellt %code% temporär, was den Aufruf seines Konstruktors beinhaltet. Dann wird der zweite Ausdruck %code% ausgewertet, der das Y ausgibt. Am Ende des vollständigen Ausdrucks wird dann das Temporäre zerstört, das seinen Destruktor aufrufen wird. Also waren deine Erwartungen richtig.
%Vor%Damit das Folgende funktioniert, sollten Sie Klammern hinzufügen, da das Komma in Deklarationen eine vordefinierte Bedeutung hat. Es würde beginnen, eine Funktion %code% zu deklarieren, die ein %code% zurückgibt und keine Parameter annimmt, und würde das Objekt %code% zu %code% zuweisen. Wenn Sie Klammern verwenden, sagen Sie, dass die ganze Sache stattdessen ein einzelner Komma-Operator-Ausdruck ist.
%Vor%Es sollte beachtet werden, dass die folgenden zwei Zeilen äquivalent sind. Der erste erstellt nicht ein temporäres unbenanntes Objekt mit %code% als Konstruktorargument, stattdessen sind die Klammern um den Namen redundant. Lass dich nicht von der Syntax verwirren.
%Vor%Ich habe einen Missbrauch der Begriffe "Umfang" und "Lebensdauer" gesehen.
%code% ist der Ort, an dem Sie auf einen Namen verweisen können, ohne seinen Namen zu qualifizieren. Namen haben Geltungsbereiche, und Objekte erben den Geltungsbereich des Namens, der für ihre Definition verwendet wurde (daher sagt der Standard manchmal "lokales Objekt"). Ein temporäres Objekt hat keinen Gültigkeitsbereich, weil es keinen Namen hat. Ebenso hat ein Objekt, das von %code% erstellt wurde, keinen Gültigkeitsbereich. Bereich ist eine Kompilierzeiteigenschaft. Dieser Begriff wird im Standard häufig missbraucht, siehe diesen Fehlerbericht . also ist es ziemlich verwirrend, eine echte Bedeutung zu finden.
%code% ist eine Laufzeiteigenschaft. Es bedeutet, wenn das Objekt eingerichtet und einsatzbereit ist. Bei einem Objekt vom Typ class beginnt die Lebensdauer, wenn der Konstruktor die Ausführung beendet, und endet, wenn der Destruktor mit der Ausführung beginnt. Die Lebenszeit wird oft mit dem Umfang verwechselt, obwohl diese beiden Dinge völlig unterschiedlich sind.
Die Lebensdauer von Provisorien ist genau definiert. Die meisten von ihnen beenden die Lebensdauer nach der Auswertung des vollständigen Ausdrucks, in dem sie enthalten sind (wie der Komma-Operator von oben oder ein Zuweisungsausdruck). Provisorien können an Const-Referenzen gebunden werden, die ihre Lebensdauer verlängern. Objekte, die in Ausnahmen ausgelöst werden, sind ebenfalls temporär und ihre Lebensdauer endet, wenn für sie kein Handler mehr existiert.
Warum gibt der folgende Code "xxY" aus? Sollten lokale Variablen nicht im Rahmen der gesamten Funktion leben? Kann ich ein solches Verhalten verwenden oder wird dies in zukünftigen C ++ - Standards geändert?
Ich dachte, dass nach C ++ Standard 3.3.2 " Ein in einem Block deklarierter Name lokal für diesen Block ist. Sein potenzieller Umfang beginnt an seinem Deklarationspunkt und endet am Ende seiner deklarativen Region. "
%Vor%Aufgrund der Antworten kann ich annehmen, dass %code% der Ausdruck (und der Gültigkeitsbereich) ist. Das ist sinnvoll. Also erwarte ich, dass der folgende Code immer "xYx" ausgibt:
%Vor%Und es ist erlaubt, einen solchen Ersatz zu machen:
%Vor%Das in Ihrem
erstellte Objekt %Vor%ist ein temporäres Objekt, das in diesem Ausdruck nur lebendig ist ;
%Vor%ist ein Objekt, das für den gesamten Block aktiv ist.
Sie haben den Standard korrekt zitiert. Lassen Sie mich betonen:
Ein Name deklariert in einem Block ist lokal für diesen Block. Sein potenzieller Geltungsbereich beginnt am Ort der Erklärung und endet am Ende seiner deklarativen Region.
Sie haben tatsächlich keinen Namen angegeben. Ihre Zeile
%Vor%enthält nicht einmal eine Deklaration ! Es enthält einen Ausdruck, der eine Instanz von MyClass erstellt, den Ausdruck berechnet (aber in diesem speziellen Fall gibt es nichts zu berechnen), und wirft sein Ergebnis auf %code% und zerstört die dort erstellten Objekte.
Eine weniger verwirrende Sache würde wie
klingen %Vor% Du hast es viele Male gesehen und weißt, wie es funktioniert, nicht wahr?Sie erstellen ein Objekt tatsächlich, ohne es in seinem Umfang zu belassen. Daher wird es direkt nach der Erstellung zerstört. Daher das Verhalten, das Sie erleben.
Sie können nicht auf das erstellte Objekt zugreifen, also warum sollte der Compiler es beibehalten?
Um Ihre anderen Fragen zu beantworten. Das folgende ist der Aufruf des Komma-Operators. Es erstellt MyClass
temporär, was den Aufruf seines Konstruktors beinhaltet. Dann wird der zweite Ausdruck cout << "Y" << endl
ausgewertet, der das Y ausgibt. Am Ende des vollständigen Ausdrucks wird dann das Temporäre zerstört, das seinen Destruktor aufrufen wird. Also waren deine Erwartungen richtig.
Damit das Folgende funktioniert, sollten Sie Klammern hinzufügen, da das Komma in Deklarationen eine vordefinierte Bedeutung hat. Es würde beginnen, eine Funktion some_func
zu deklarieren, die ein int
zurückgibt und keine Parameter annimmt, und würde das Objekt scoped_lock
zu x
zuweisen. Wenn Sie Klammern verwenden, sagen Sie, dass die ganze Sache stattdessen ein einzelner Komma-Operator-Ausdruck ist.
Es sollte beachtet werden, dass die folgenden zwei Zeilen äquivalent sind. Der erste erstellt nicht ein temporäres unbenanntes Objekt mit my_mutex
als Konstruktorargument, stattdessen sind die Klammern um den Namen redundant. Lass dich nicht von der Syntax verwirren.
Ich habe einen Missbrauch der Begriffe "Umfang" und "Lebensdauer" gesehen.
Scope
ist der Ort, an dem Sie auf einen Namen verweisen können, ohne seinen Namen zu qualifizieren. Namen haben Geltungsbereiche, und Objekte erben den Geltungsbereich des Namens, der für ihre Definition verwendet wurde (daher sagt der Standard manchmal "lokales Objekt"). Ein temporäres Objekt hat keinen Gültigkeitsbereich, weil es keinen Namen hat. Ebenso hat ein Objekt, das von new
erstellt wurde, keinen Gültigkeitsbereich. Bereich ist eine Kompilierzeiteigenschaft. Dieser Begriff wird im Standard häufig missbraucht, siehe diesen Fehlerbericht . also ist es ziemlich verwirrend, eine echte Bedeutung zu finden.
Lifetime
ist eine Laufzeiteigenschaft. Es bedeutet, wenn das Objekt eingerichtet und einsatzbereit ist. Bei einem Objekt vom Typ class beginnt die Lebensdauer, wenn der Konstruktor die Ausführung beendet, und endet, wenn der Destruktor mit der Ausführung beginnt. Die Lebenszeit wird oft mit dem Umfang verwechselt, obwohl diese beiden Dinge völlig unterschiedlich sind.
Die Lebensdauer von Provisorien ist genau definiert. Die meisten von ihnen beenden die Lebensdauer nach der Auswertung des vollständigen Ausdrucks, in dem sie enthalten sind (wie der Komma-Operator von oben oder ein Zuweisungsausdruck). Provisorien können an Const-Referenzen gebunden werden, die ihre Lebensdauer verlängern. Objekte, die in Ausnahmen ausgelöst werden, sind ebenfalls temporär und ihre Lebensdauer endet, wenn für sie kein Handler mehr existiert.