2010-10-09 28 views
11

Después de una extensa lectura de ISO/IEC 14882, Programming language – C++ Todavía estoy seguro de por qué const se necesita para la conversión implícita de un tipo definido por el usuario con un único constructor sin argumentos como el siguiente¿Por qué const para la conversión implícita?

#include <iostream> 

class X { 
public: 
    X(int value) { 
     printf("constructor initialized with %i",value); 
    } 
} 

void implicit_conversion_func(const X& value) { 
    //produces "constructor initialized with 99" 
} 

int main (int argc, char * const argv[]) { 
    implicit_conversion_func(99); 
} 



Comenzando con la sección 4 línea 3

Una expresión e se puede convertir implícitamente en un tipo T si y solo si la declaración T t = e; está bien formado, por alguna variable temporal inventada t (8.5). Ciertas construcciones de lenguaje requieren que una expresión se convierta en un valor booleano. Se dice que una expresión e que aparece en dicho contexto se convierte contextualmente a bool y está bien formada si y solo si la declaración bool t (e); está bien formado, por alguna variable temporal inventada t (8.5). El efecto de cualquiera de las conversiones implícitas es el mismo que realizar la declaración y la inicialización y luego usar la variable temporal como resultado de la conversión. El resultado es un lvalue si T es un tipo de referencia lvalue (8.3.2), y un valor r de otra manera. La expresión e se usa como un valor l si y solo si la inicialización lo usa como un valor l.

Después de haber encontrado el apartado de inicializadores relacionadas con los tipos definidos por el usuario en 8.5 línea 6

Si un programa llama a la inicialización por defecto de un objeto de un tipo T const cualificado, T será un tipo de clase con un constructor predeterminado proporcionado por el usuario.

Finalmente I finalizó en 12,3 línea 2 acerca de las conversiones definidas por el usuario que establece

conversiones definidas por el usuario se aplican sólo donde están los inequívoca (10.2, 12.3.2).

No hace falta decir que 10.2 y 12.3.2 no respondieron mi pregunta.

  1. Puede alguien arrojar alguna luz sobre el efecto que tiene sobre const conversiones implícitas?
  2. ¿El uso de const hace que la conversión sea "no ambigua" por 12.3 línea 2?
  3. ¿De alguna manera afecta const a lvalue vs. rvalue de la sección 4?
+1

¿No te encanta C++? –

Respuesta

13

Realmente no tiene mucho que ver con la conversión implícita. Además, en realidad no tiene mucho que ver con conversiones. Se trata realmente de rvalues ​​ frente a lvalues ​​.

Al convertir 99 para escribir X, el resultado es un valor p . En C++, los resultados de las conversiones son siempre rvalues ​​(a menos que se convierta en tipo de referencia). Es ilegal en C++ adjuntar referencias no const a rvalues.

Por ejemplo, este código no se compilará

X& r = X(99); // ERROR 

porque intenta adjuntar una referencia no const a un valor p. Por otra parte, este código está bien

const X& cr = X(99); // OK 

porque es perfectamente bien para adjuntar una referencia constante a un valor de lado derecho.

Lo mismo sucede en su código también. El hecho de que implique una conversión implícita es un poco más allá del punto. Puede reemplazar la conversión implícita con una explícita uno

implicit_conversion_func(X(99)); 

y terminan con la misma situación: con const compila, sin const no lo hace.

Nuevamente, la única función que desempeña la conversión (explícita o implícita) aquí es que nos ayuda a producir un valor r. En general, se puede producir un valor de lado derecho de alguna otra manera y correr en la misma edición

int &ir = 3 + 2; // ERROR 
const int &cir = 3 + 2; // OK 
+0

"_Cuando se convierte 99 en tipo X, el resultado es un rvalue._" No. ** Un rvalue es una expresión. ** Conversión de '99' a' X' da como resultado un objeto temporal. – curiousguy

+0

@curiousguy: Si bien el concepto de "rvalue" está firmemente vinculado a la expresión, el término "rvalue" puede usarse para referirse tanto a la expresión en sí como al resultado que produce. El estándar de lenguaje realmente usa el concepto de "resultado rvalue" mucho más a menudo que de "expresión rvalue". (Obviamente, ambos están destinados a referirse a la misma cosa). Además, la especificación del lenguaje establece clara y explícitamente en 5.2.3 que el resultado del caso de estilo funcional es un valor r. Período. El hecho de que también sea "un objeto temporal" no es relevante aquí. – AnT

+0

¿Podría explicar qué significa "rvalue"? – curiousguy

0

Según la sección 5.2.2 párrafo 5, cuando un argumento de una función es de const tipo de referencia, una variable temporal es automáticamente introducido si es necesario. En su ejemplo, el resultado rvalue de X(99) debe colocarse en una variable temporal para que esa variable se pueda pasar por const referencia a implicit_conversion_func.

+0

"_el rvalue 99 tiene que colocarse en una variable temporal para que esa variable se pueda pasar por (const) referencia al constructor de X_" No. El parámetro del constructor se pasa por valor; no hay referencia constante a 'int', y no es temporal con el valor 99." _ La semántica de crear un no-const temporal en cualquier caso sería bastante confuso_ "¿Qué pasa con' std :: string() = "Hola, mundo "'? – curiousguy

+0

@curiousguy Buen punto - Creo que leí mal el OP. El temporal es una 'const X' inicializada construyendo con' 99' como argumento, no como 'const int'. Sin embargo, su esencia sigue siendo: se crea un 'const' temporal para satisfacer el argumento' const & '. –

Cuestiones relacionadas