c++ - sirve - Tratar implícitamente el valor de l devuelto como valor de r
return 0 en java (2)
12.8 Copiar y mover objetos de clase [class.copy] §31 y §32 dicen:
en una declaración de retorno en una función con un tipo de retorno de clase, cuando la expresión es el nombre de un objeto automático no volátil (que no sea un parámetro de función o cláusula catch) con el mismo tipo no calificado cv que el tipo de retorno de función, la operación de copiar / mover se puede omitir construyendo el objeto automático directamente en el valor de retorno de la función
Cuando los criterios para la elección de una operación de copia se cumplen o se cumplirían, salvo por el hecho de que el objeto de origen es un parámetro de función, y el objeto que se va a copiar se designa mediante un lvalor, la resolución de sobrecarga para seleccionar el constructor para la copia es Primero se realiza como si el objeto fuera designado por un valor de r.
Por lo tanto podemos escribir:
unique_ptr<int> make_answer()
{
unique_ptr<int> result(new int(42));
return result; // lvalue is implicitly treated as rvalue
}
Sin embargo, me di cuenta de que g ++ 4.6.3 también acepta lvalues que no son nombres , por ejemplo:
return (result);
return *&result;
return true ? result : result;
Por el contrario, return rand() ? result : result;
return rand() ? result : result;
No funciona. ¿Está el optimizador del compilador interfiriendo con la semántica del lenguaje? A medida que interpreto la norma, return (result);
no debe compilar, porque (result)
no es un nombre, sino una expresión entre paréntesis. ¿Estoy en lo correcto o incorrecto?
Respecto a las expresiones entre paréntesis [√]
Se equivoca al hablar de expresiones entre paréntesis y no debería poder activar un movimiento cuando se devuelve y contiene solo el nombre de un objeto movible .
5.1.1 / 1 General [expr.prim.general]
Una expresión entre paréntesis es una expresión principal cuyo tipo y valor son idénticos a los de la expresión encerrada. La presencia de paréntesis no afecta si la expresión es un valor l. La expresión entre paréntesis puede usarse exactamente en los mismos contextos que aquellos en los que se puede usar la expresión encerrada , y con el mismo significado , excepto que se indique lo contrario.
Respecto al operador condicional constexpr [╳]
La forma en que interpreto el estándar en lo que respecta a las expresiones constantes y el operador de código es que el uso de return true ? result : result
return true ? result : result
se comporta bien porque es una expresión constante y, por lo tanto, es equivalente a devolver el resultado;
Ahora he revisado el estándar con más cuidado y en ninguna parte dice que una expresión condicional constante es lo mismo que si solo se hubiera escrito la expresión "devuelta" .
true ? <expr1> : <expr2>; // this is not the same as just writing <expr1>;
Respecto a la devolución * y resultado; [╳]
En C99 se establece explícitamente que *&result
es el equivalente exacto de haber escrito el result
lugar, este no es el caso en la especificación de C ++.
Aunque todos podemos estar de acuerdo en que usar *&result
hecho producirá el mismo lvalor que el result
, pero de acuerdo con el estándar *&result
(por supuesto) no es una expresión donde "la expresión es el nombre de un objeto automático no volátil" .
Claro, la expresión contiene un nombre apropiado, pero no es solo eso.
Para resumir las cosas ...
return result; // #1, OK
return (result); // as described earlier, OK
return true ? result : result; // as described earlier, ill-formed
return rand () ? result : result; // as described earlier, ill-formed
return *&result; // as described earlier, ill-formed
Las expresiones entre paréntesis son equivalentes a sus expresiones sin paréntesis, a menos que se indique lo contrario (como se hace en las reglas de ADL, por ejemplo, o por decltype para otro ejemplo). A veces puede ser complicado cuando, y cuando no, algo es equivalente de esta manera (por ejemplo, las reglas de ADL no mencionan explícitamente "sin paréntesis", pero usan una gramática explícita no terminal y ejemplos que dejan en claro que los parens no están tomado como equivalente).
Para las otras preguntas: Sí, GCC realiza varias optimizaciones en el AST directamente que lo hacen aceptar varios programas no válidos, como los siguientes
int a = 42;
int *p = 0 * a;