In C ++, welche Kategorien (lvalue, rvalue, xvalue usw.) können Ausdrücke enthalten, die Provisorien des Klassentyps erzeugen?

8

Hier ist ein Beispielcode:

%Vor%

Sind Ausdrücke wie Foo (5) prvalues ​​oder allgemeine rvalues? Ist die Tatsache, dass ich get_addr () für diese Ausdrücke aufrufen kann, eine Identität? Oder bedeutet die Tatsache, dass ich den Standard & amp; -Operator nicht anwenden kann (ich meine nicht überladen), dass sie keine Identität haben und daher prvalues ​​sind?

Ist es auch fair zu sagen, dass die Veränderlichkeit des produzierten Wertes über den Ausdruck, der ihn erzeugt hat, orthogonal zu dieser Wertklassifikation ist?

    
CppNoob 21.12.2013, 08:41
quelle

2 Antworten

16

Jeder Ausdruck ist einer und nur einer von:

  • lvalue
  • xvalue
  • prvalue

Die Vereinigung von Ausdrücken, die lvalues ​​und xvalues ​​sind, werden kollektiv als glvalues ​​ bezeichnet.

Die Vereinigung von Ausdrücken, die xvalues ​​und prvalues ​​sind, werden gemeinsam als rvalues ​​ bezeichnet.

Somit sind xvalue-Ausdrücke sowohl als glvalues ​​als auch als rvalues ​​bekannt.

Das handliche Diagramm, das in Alf gefunden wurde, zeigt die Beziehung, die ich beschrieben habe, richtig mit Wörtern darüber, und wird auch in Abschnitt 3.10 der C ++ - Standards, Versionen C ++ 11 und höher gefunden.

Alles, was ich oben gesagt habe, vermute ich, dass das OP bereits wusste, nur aus dem Wortlaut des Titels dieser Frage.

Wissenswertes:

  

Bjarne Stroustrup erfand diese Klassifikation von Ausdrücken und   dabei speicherte vielleicht der gesamte rvalue reference proposal ab   kollabiert in der Kernarbeitsgruppe. Ich werde für immer dankbar sein.

Was ich hinzufügen möchte, ist eine Möglichkeit, für sich selbst herauszufinden, auf welche der drei untersten Klassifizierungskategorien sich ein Ausdruck bezieht: lvalue, xvalue oder prvalue.

%Vor%

Die obige Funktion kann wie folgt verwendet werden:

%Vor%

Und es wird die Frage dieses OP beantworten. Zum Beispiel:

%Vor%

Für mich druckt:

%Vor%

Ein Bereich, auf den Sie bei der Verwendung dieser Funktion achten sollten:

decltype(variable_name) gibt den deklarierten Typ des Variablennamens an. Wenn Sie die Wertkategorie des Ausdrucks ermitteln möchten, wenn variable_name verwendet wird (im Gegensatz zu dem deklarierten Typ), müssen Sie zusätzliche Klammern um (variable_name) einfügen, wenn sie in decltype verwendet werden. . Das ist:

%Vor%

ist der Typ des Ausdrucks variable_name und nicht der deklarierte Typ von variable_name .

Zum Beispiel gegeben:

%Vor%

Dies wird fälschlicherweise ausgegeben:

%Vor%

Fügen Sie die zusätzlichen Klammern zu decltype hinzu:

%Vor%

um foo von einem Typnamen in einen Ausdruck zu konvertieren. Jetzt ist die Ausgabe:

%Vor%

Wenn Sie nicht sicher sind, ob Sie Klammern hinzufügen müssen oder nicht, um die richtige Antwort zu erhalten, fügen Sie sie einfach hinzu. Wenn Sie sie hinzufügen, führt dies nicht zu einer falschen Antwort - es sei denn, Sie suchen nach dem deklarierten Typ einer Variablen und nicht nach dem Typ eines Ausdrucks. Und im letzteren Fall möchten Sie eine eng verwandte Funktion: type_name<T>() .

    
Howard Hinnant 21.12.2013, 17:54
quelle
6

Jeder Ausdruck in C ++ ist entweder ein lvalue oder ein rvalue . Daher fragen Sie nach den Klassifikationen, die rvalues ​​sind. Schauen Sie sich hierzu die Abbildung des Klassifikationsbaums im C ++ 11-Standard §3.10 / 1 an.

Weitere Informationen (ohne sich mit dem Standard vertraut zu machen) finden Sie unter Was? rvalues, lvalues, ... .

Betreffend

  

"Sind Ausdrücke wie Foo (5) rvalues ​​oder prvalue"

ein Pr-Wert ist ein R-Wert notwendig - denn es könnte nicht sehr gut ein L-Wert sein.

Ein prvalue "(" reiner "rvalue) ist ein rvalue, der kein xvalue ist, und ein xvalue ist" das Ergebnis bestimmter Arten von Ausdrücken, die rvalue-Referenzen "Ein Konstruktoraufruf erzeugt keine rvalue-Referenz, daher ist es kein xvalue. Also ist der rvalue ein prvalue, ein reiner rvalue.

    
Cheers and hth. - Alf 21.12.2013 08:50
quelle