2010-02-17 12 views
18

§5.3.1 operadores unarios, Sección 3tomar la dirección de un objeto temporal

El resultado de la & operador unitario es un puntero a su operando. El operando debe ser un lvalue o una identificación válida.

¿Qué significa "shall be" en este contexto? ¿Significa que es un error tomar la dirección de un temporal? Me preguntaba, porque g ++ sólo me da una advertencia, mientras que Comeau se niega a compilar el programa siguiente:

#include <string> 

int main() 
{ 
    &std::string("test"); 
} 

g ++ advertencia: taking address of temporary

comeau error: expression must be an lvalue or a function designator

¿El Alguien tiene un compilador de Microsoft u otros compiladores y puede probar este programa, por favor. Gracias por adelantado.

+0

eso es interesante. No tengo ninguna experiencia con Comeau, pero me pregunto si se está confundiendo debido a la plantilla. ¿Qué sucede si solo prueba algo como & array [0]; donde matriz es alguna matriz creada? – Casey

+0

& Casey & array [0] es perfectamente legal - array [0] es un lvalue –

Respuesta

21

La palabra "shall" en el idioma estándar significa un requisito estricto.Entonces, sí, su código está mal formado (es un error) porque intenta aplicar el operador de dirección a un valor no-l.

Sin embargo, el problema aquí no es un intento de tomar la dirección de temporal. El problema es, una vez más, tomar la dirección de non-lvalue. El objeto temporal puede ser lvalue o non-lvalue dependiendo de la expresión que produce ese temporal o proporciona acceso a ese temporal. En su caso, tiene std::string("test") - un estilo funcional emitido a un tipo que no es de referencia, que por definición produce un valor no-l. De ahí el error.

Si desea tomar la dirección de un objeto temporal, que podrían haber trabajado en torno a la restricción al hacer esto, por ejemplo

const std::string &r = std::string("test"); 
&r; // this expression produces address of a temporary 

un poco con el puntero resultante siga siendo válido, siempre y cuando exista el temporal. Hay otras maneras de obtener legalmente la dirección de un objeto temporal. Es solo que su método específico pasa a ser ilegal.

+5

+1 por diferencia de rvalue y temporal. Las personas los hacen iguales a menudo, pero no lo son en absoluto. Un ejemplo común son los objetos de excepción, que son lvalues ​​y se pueden vincular a un 'T &' en una cláusula catch. –

+1

De hecho, el Estándar en sí parece hacer un uso incorrecto del término "temporal", si no me equivoco. Dice que un límite temporal a un retorno de función debería destruirse después de que la función regrese. Sin embargo, esto significa que 'struct A {A & ref() {i ++; devuelve * esto; } int i; }; int main() {A(). ref(). ref(); } 'invoca comportamiento indefinido, porque después del primer' ref() ', el objeto ya no existe. Se omite decir que solo se consideran esos objetos, que aún no se han vinculado a una referencia (incluido el parámetro de objeto implícito). –

+0

@ JohannesSchaub-litb "_Dice que un límite temporal al retorno de una función debe destruirse después de que la función retorne._" Parece que temporal y rvalue se usan como si fueran sinónimos. – curiousguy

4

Cuando se utiliza la palabra "shall" en el estándar C++, significa "debe so pena de muerte": si una implementación no obedece a esto, es incorrecta.

+0

-1. En realidad, esto se aplica solo a aquellas declaraciones del formulario "la implementación debe hacer X". Las declaraciones de la forma "el código de entrada debe hacer X", significa "debe so pena de diagnóstico". – MSalters

+2

@MSalters Debe en caso de muerte un diagnóstico. –

+3

@MSalters Y por cierto, siempre pensé que era una práctica dudosa rechazar las respuestas a una pregunta a la que usted mismo está respondiendo. –

-1

No soy un experto en estándares, pero ciertamente me parece un error. g ++ muy a menudo solo da una advertencia para cosas que realmente son errores.

4

Está permitido en MSVC con la opción obsoleto/Ze (extensiones habilitadas). Fue permitido en versiones anteriores de MSVC. Genera un diagnóstico con todas las advertencias habilitadas:

advertencia C4238: extensión no estándar utilizada: class rvalue utilizado como lvalue.

menos que se utilice la opción/Za (cumplir compatibilidad ANSI), entonces:

error C2102: '&' requiere l-valor

0

&std::string("test"); está pidiendo la dirección de el valor de retorno de la llamada a la función (ignoraremos como irrelevante el hecho de que esta función sea un ctor). No tenía una dirección hasta que lo asignó a algo. Por lo tanto, es un error.

+0

Por supuesto, puede tomar la dirección de los valores de retorno de llamada de función, siempre que sean valores l. –

+0

Pero si llama a una función, ¿no es eso por definición un valor? – TMN

+2

@TMN No - en C++ puede devolver una referencia, que es un valor l. Así es como funcionan cosas como operador [] para std :: vector. –

1

El estándar de C++ es realmente un requisito en las implementaciones conformes de C++. En los lugares, está escrito para distinguir entre códigos que las implementaciones conformes deben aceptar y codificar para las implementaciones conformes que deben proporcionar un diagnóstico.

Por lo tanto, en este caso particular, un compilador conforme debe dar un diagnóstico si se toma la dirección de un valor r. Ambos compiladores lo hacen, por lo que son conformes en este sentido.

La norma no prohíbe la generación de un archivo ejecutable si una determinada entrada causa un diagnóstico, es decir, las advertencias son diagnósticos válidos.

Cuestiones relacionadas