2012-07-20 9 views
22

Estoy tratando de entender los conceptos de C++ 11.¿Qué expresiones crean valores x?

El proyecto de norma que tengo dice:

Un xValue (un “expira” valor) también se refiere a un objeto, por lo general cerca del final de su vida útil (de modo que sus recursos pueden ser movidos, por ejemplo). Un xvalor es el resultado de ciertos tipos de expresiones que implican referencias de valores (8.3.2). [Ejemplo: El resultado de llamar a una función cuyo tipo de devolución es un valor de referencia es un valor x. -fin ejemplo]

OK, entonces ¿qué es exactamente son los "ciertos tipos de expresiones" que producen XValues? Esta parte de la especificación no detalla una lista de estas expresiones.

Entiendo lvalue y prvalue (al menos creo, entiendo).

+2

Una respuesta completa: [¿Qué son rvalues, lvalues, xvalues, glvalues, y prvalues?] (Http://stackoverflow.com/questions/3601602/what-are-rvalues-lvalues-xvalues-glvalues-and-prvalues) – pmr

+1

Esa parte de la norma explica la comprensión general del término. No detalla cada tipo de expresión que genera un xvalor. Eso sucede en cualquier otro lugar de la norma. –

+0

@NicolBolas: He leído esa pregunta y respuestas antes y decidí publicar otra pregunta exactamente por este motivo. – PermanentGuest

Respuesta

18

Hay una nota útil no normativa en la introducción a § 5 (C++ 11 § 5 [expr]/6):

[Nota: Una expresión es un xValue si es:

  • el resultado de llamar a una función, ya sea implícita o explícitamente, cuyo tipo de retorno es una referencia a rvalue tipo de objeto,

  • un molde a una referencia a rvalue tipo de objeto,

  • una expresión acceso miembro de la clase que designa un miembro no estático de datos de tipo no es de referencia en el que la expresión objeto es un xValue, o

  • un .* expresión-puntero a miembro en el que el primer operando es un xvalor y el segundo operando es un puntero al miembro de datos.

En general, el efecto de esta regla es que las referencias rvalue nombradas son tratados como lvalues ​​y referencias rvalue sin nombre a los objetos se tratan como XValues; Las referencias a las funciones de rvalue se tratan como lvalues, ya sean nombrados o no. -finalizar]

Buscando en el resto del §5, esta lista parece exhaustiva. La lista es seguido por un ejemplo:

struct A { 
    int m; 
}; 

A&& operator+(A, A); 
A&& f(); 
A a; 
A&& ar = static_cast<A&&>(a); 

Las expresiones f(), f().m, static_cast<A&&>(a), y a + a son XValues. La expresión ar es un lvalue.

Hay dos formas comunes para conseguir una expresión xValue:

  • Uso std::move Para mover un objeto. std::move realiza un static_cast a un tipo de referencia rvalue y devuelve la referencia rvalue.

  • Usa std::forward para reenviar un valor. std::forward se usa típicamente en una plantilla de función para permitir el reenvío perfecto de un argumento de función.

    Si el argumento proporcionado a la plantilla de función fue un valor r, el tipo de parámetro será una referencia rvalue, que es un valor l. En este caso, std::forward realiza un static_cast en un tipo de referencia rvalue y devuelve la referencia rvalue.

    (Nota: Si el argumento proporcionado a la plantilla de función fue un lvalue, el tipo de parámetro será una referencia lvalue y std::forward devolverá una referencia lvalue.)

+1

Boo, justo cuando estaba construyendo mi lista de ejemplos y tropecé con la cita. :(+1, debería haber hecho la edición de la etiqueta después de que terminé mi respuesta. :) – Xeo

+0

Gracias por la lista detallada ... esto combinado con otras respuestas y mucho otro Google borró las confusiones sobre la definición básica. – PermanentGuest

+0

Respuesta muy útil, pero un punto aún escapa a mi comprensión. Entiendo eso en 'Foo bar() {Foo foo; return foo;} ', la expresión' foo' es un valor x en la declaración return (corrija si es incorrecto). No veo que esté cubierto por la lista que citó. – ricab

6

la cláusula 5, que describe la sintaxis de expresiones válidas, enumera para cada sintaxis de expresión las condiciones en las que la expresión es un valor l, un valor xo un valor pr. La lista completa de xvalues ​​posibles de la cláusula 5 es:

5.2.2 párrafo 10: Una llamada a función es ... un xvalor si el tipo de resultado es una referencia rvalue al tipo de objeto.

(En el lenguaje técnico de la Norma, "Tipo de objeto" no significa lo mismo que "tipo de clase". "Tipo de objeto" incluye tipos fundamentales, punteros y matrices, y sólo excluye los tipos de función. Una referencia rvalue al tipo de función siempre se trata como un valor lvalue, no xvalue.)

Las funciones más notables que devuelven una referencia rvalue son, por supuesto, std::move y algunas veces std::forward.

5.2.5 párrafo 4: Si E2 es un miembro de datos no estáticos ... si E1 es un xValue, entonces E1.E2 es un xValue

(Por otra parte, un miembro de datos lookup E1->E2 es siempre un valor-i)

mismo modo, si E1 es un xValue, a continuación, la búsqueda miembro de datos E1.*E2 es un xValue:.

5.5 párrafo 6: El resultado de una expresión .* cuyo segundo operando es un puntero a un miembro de datos tiene la misma categoría de valor (3.10) que su primer operando.

Para los diferentes tipos de moldes:

  • dynamic_cast<Type>(expr): 5.2.7 párrafo 2
  • static_cast<Type>(expr): 5.2.9 párrafo 1
  • reinterpret_cast<Type>(expr): 5.2.10 párrafo 1
  • const_cast<Type>(expr) : 5.2.11 párrafo 1
  • (Type) expr: 5.4 párrafo 1

la expresión es un xvalor si y solo si Type es una referencia rvalue al tipo de objeto.Lo mismo también es cierto para , ya

5.2.3 párrafo 1: Si la lista de expresiones [paréntesis siguientes un nombre de tipo] es una sola expresión, la expresión de conversión de tipo es equivalente (en definedness, y si definido en significado) a la expresión de conversión correspondiente (5.4).

(Por otra parte, Type{expr} es siempre una prvalue.)

Sección 5.16 en el operador condicional termina diciendo que A ? B : C a veces puede ser un xValue si B y/o C es un xValue. Pero las reglas completas son difíciles de resumir.

Si una expresión termina llamando a una función de operador sobrecargada definida por el usuario, la sección 5.2.2 se aplica a esa expresión, no la que describe el comportamiento del operador incorporado. (Ver la expresión a + a en el ejemplo @ James registró.)

0

Lo que deduzco de lo que he leído es que llamar a algo un xValue es una forma elegante de decir:

Un xValue es sólo un valor de lado derecho cuya el almacenamiento puede haber sido desasignado, por lo que usarlo significa que tiene que verificar su existencia usted mismo.

Generalmente, hay uno o más niveles de indirección lejos de un valor real.

Por el contrario, se garantiza que un valor r tendrá su espacio de almacenamiento existente siempre que esté dentro del alcance.

Puedo estar equivocado, pero esto es lo que he entendido.

+5

No, un valor x es un valor que sigue siendo válido, pero está a punto de descartarse.Lo que generalmente significa que es seguro hacer cosas como "robar" recursos de él y escribir sobre su valor existente. – aschepler

+0

@aschepler: Por ejemplo, el tipo de retorno de '[]() {int x = 5; return std :: move (x); } '¿no es un valor x? Si no, entonces ¿qué es? – Mehrdad

+2

Los tipos no tienen categorías de valores; expresiones hacer. – aschepler

Cuestiones relacionadas