2008-09-17 13 views

Respuesta

16

1: No se permite tomar la dirección de un temporal. Visual C++ lo permite como una extensión de idioma (las extensiones de idioma están activadas por defecto).

2: Esto es perfectamente legal.

+1

, está prohibido tomar la dirección de un rvalue, no un temporal específicamente. es por eso que esto está prohibido; 'A()' devuelve un valor r. –

+2

@underscore_d Verdadero: utilicé el término informal 'temporal', más específicamente una variable temporal sin nombre, y, como bien dices, un valor r. Si estamos siendo quisquillosos, 'A()' no 'devuelve' un valor r (los constructores no tienen valores devueltos), es una expresión prvalue. –

+0

Buena captura: es demasiado fácil pensar reflexivamente en constructores como llamadas a funciones. –

-2

perfectamente legal.

El objeto existirá en la pila durante la llamada a la función, al igual que cualquier otra variable local.

0

se veía lke que iba a funcionar, pero no compila con g ++ con la opción de pared, esto es lo que me sale:

 
[email protected]:~/Desktop$ g++ -Wall a.cpp 
a.cpp: In function ‘int main()’:[email protected]:~/Desktop$ g++ -Wall a.cpp 
a.cpp: In function ‘int main()’: 
a.cpp:8: warning: taking address of temporary 
a.cpp:9: error: invalid initialization of non-const reference of type ‘A&’ from a temporary of type ‘A’ 
a.cpp:4: error: in passing argument 1 of ‘void bar(A&)’ 
[email protected]:~/Desktop$ 

Parece que tendrá que utilizar una referencia constante.

+0

Pero el hecho de que tanto MSVC como g ++ emitan advertencias para (1) sugiere que puede no ser 100% legal. ¿Tiene una sección de la cita estándar de C++? –

1

Esos objetos A solo existirán hasta que la ejecución alcance el punto y coma. Por lo tanto, las llamadas son seguras, pero no intente guardar el puntero y usarlo más adelante. Además, el compilador puede requerir que la barra tome una referencia constante.

+0

'foo (& A()) podría ser" seguro ", si se compila. No es válido C++. –

-1

Es legal. Lo usamos en algún momento para proporcionar un valor predeterminado que es posible que deseemos ignorar.

int dosomething(error_code& _e = ignore_errorcode()) { 
    //do something 
} 

En el caso anterior Será construir un objeto de código de error vacía si no error_code se pasa a la función.

+0

Estoy bastante seguro de que ignore_errorcode() devuelve un objeto error_code con más vida que un objeto creado por un constructor predeterminado ... – Pieter

-1

para // 2 necesita una referencia const

de 1 // Creo que es legal, pero inútil

+0

No, 'foo (& A())' no es legal porque 'A()' es un valor r, y no puede tomar la dirección de un valor r. http://stackoverflow.com/a/2985578/2757035 –

9

No, es en contra de la norma para pasar una referencia no const a un objeto temporal. Puede utilizar una referencia constante:

class A{}; 

void bar(const A&); 

int main(void) 
{ 
    bar(A()); // 2 
} 

Así, mientras que algunos cumplidores lo aceptarán, y que iba a funcionar, siempre y cuando no se utilice la memoria después del punto y coma, un compilador conforme no lo aceptará.

+4

Esta respuesta está desactualizada por una edición de OP –

5

foo no está permitido en ++ C compatible totalmente estándar, mientras que bar está bien. Aunque es probable que foo compile con advertencia, y bar puede compilar o no con una advertencia también.

A() crear un objeto temporal, que a menos que unido a una referencia (como es el caso en bar), o utilizado para inicializar un objeto nombrado, se destruye al final de la expresión completa en la que fue creado. Un temporal creado para mantener un inicializador de referencia persiste hasta el final del alcance de su referencia.Para el caso de bar, esa es la llamada a la función, por lo que puede usar A dentro de bar con total seguridad. Está prohibido vincular un objeto temporal (que es un valor r) a una referencia no constante. De manera similar, está prohibido tomar la dirección de un valor r (para pasar como argumento para inicializar A para foo).

+0

Necesita algunas refactorizaciones para aclarar las capacidades de mejora del alcance de una referencia sobre una variable temporal. –

+0

Esta es la respuesta superior porque hace bien en que lo que está prohibido es tomar la dirección de un rvalue, no un temporal específicamente. –

2

La respuesta breve es sí.

Si el objeto se recibe por función como parámetro de referencia const - como ha modificado el método bar(const A&), entonces es totalmente legal. La función puede operar en el objeto, pero el objeto se destruirá después de la llamada a la función (se puede tomar la dirección temporal, pero no se debe almacenar y usar después de la llamada a la función - ver el motivo a continuación).

El foo(A*) es legal también porque el objeto temporal se destruye al final de la carga completa. Sin embargo, la mayoría del compilador emitirá una advertencia acerca de tomar la dirección de temporal.

La versión original de bar(A&) no se compilará, es contrario al estándar inicializar una referencia no constante de una temporal.

C++ capítulo estándar 12,2

3 [...] objetos temporales se destruyen como el último paso en la evaluación de la fullexpression (1.9) que (léxico) contiene el punto en el que fueron creados. [...]

4 Hay dos contextos en los que los temporales se destruyen en un punto diferente al final de la vista completa. El primer contexto es cuando aparece una expresión como un inicializador para un declarador que define un objeto. En ese contexto, el temporal que contiene el resultado de la expresión persistirá hasta que se complete la inicialización del objeto. [...]

5 El segundo contexto es cuando una referencia está vinculada a un temporal. El temporal al que se enlaza la referencia o el temporal que es el objeto completo de un subobjeto del cual el temporal está vinculado persiste durante el tiempo de vida de la referencia, excepto como se especifica a continuación. Un límite temporal a un miembro de referencia en un ctorinitializer (12.6.2) del constructor persiste hasta que el constructor sale. Un límite temporal a un parámetro de referencia en una llamada a función (5.2.2) persiste hasta la finalización de la expresión completa que contiene la llamada. Un límite temporal al valor devuelto en una declaración de devolución de función (6.6.3) persiste hasta que la función finaliza.

A fullexpression es una expresión que no es una subexpresión de otra expresión.

+0

No, 'foo (& A())' no es legal porque 'A()' es un valor r, y no puede tomar la dirección de un valor r. http://stackoverflow.com/a/2985578/2757035 –

Cuestiones relacionadas