valores valor tipos retornan referencias referencia que por paso parametros parametro funciones c++

c++ - valor - ¿Es legal pasar un objeto recién construido por referencia a una función?



referencias en c++ (9)

Específicamente, ¿es el siguiente C ++ legal?

class A{}; void foo(A*); void bar(const A&); int main(void) { foo(&A()); // 1 bar(A()); // 2 }

Parece que funciona correctamente, pero eso no significa que sea necesariamente legal. ¿Lo es?

Editar - cambió A& to const A&


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.


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, construirá un objeto de código de error vacío si no se pasa ningún código de error a la función.


Esos objetos A solo existirán hasta que la ejecución llegue al 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.


No, está en contra del estándar pasar una referencia no constante a un objeto temporal. Puede usar una referencia constante:

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

Entonces, aunque algunos cumplidores lo aceptarán, y funcionaría siempre y cuando no utilicen la memoria después del punto y coma, un compilador compatible no lo aceptará.


Parecía que funcionaría, pero no compilaba con g ++ con la opción Muro, esto es lo que obtengo:

michael@hardy-lenovo:~/Desktop$ g++ -Wall a.cpp a.cpp: In function ‘int main()’:michael@hardy-lenovo:~/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&)’ michael@hardy-lenovo:~/Desktop$

Parece que necesitará usar una referencia constante.


Perfectamente legal.

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


para // 2 necesitas una referencia constante

para // 1, creo que es legal pero inútil


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

A () crea un objeto temporal, que a menos que esté vinculado a una referencia (como en el caso de la barra ) o se use para inicializar un objeto nombrado, se destruye al final de la expresión completa en la que se creó. Un temporal creado para mantener un inicializador de referencia persiste hasta el final del alcance de su referencia. Para el caso de la barra , esa es la llamada a la función, por lo que puede utilizar una barra interna perfectamente segura. 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 ).


La respuesta corta es sí.

Si el objeto se recibe por función como parámetro de referencia const - como has 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 porque el objeto temporal se destruye al final de la fullexpresión. Sin embargo, la mayoría del compilador emitirá una advertencia acerca de tomar la dirección de temporal.

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

C ++ estándar capítulo 12.2

3 [...] Los objetos temporales se destruyen como el último paso para evaluar la fullexpression (1.9) que (léxicamente) contiene el punto donde fueron creados. [...]

4 Hay dos contextos en los que los temporales se destruyen en un punto diferente que el final de la expresión fullex. 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 enlace temporal a un miembro de referencia en un ctorinicializador de constructor (12.6.2) persiste hasta que el constructor finaliza. 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.

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