2010-01-18 11 views
10

¿Cómo funciona el siguiente código en C++? ¿Es lógico?Inicialización literal para referencias const

const int &ref = 9; 
const int &another_ref = ref + 6; 

¿Por qué C++ permite la inicialización literal para referencias const cuando el mismo no está permitida para las referencias no constante? Ej .:

const int days_of_week = 7; 
int &dof = days_of_week; //error: non const reference to a const object 

Esto puede explicarse por el hecho de que, una referencia no const se puede utilizar para cambiar el valor de la variable que se está refiriendo. Por lo tanto, C++ no permite una referencia no const a una variable const.

¿Podría ser esta una posible explicación? C++ no permite:

int &ref = 7; 

Debido a que no es lógico, pero:

const int &ref = 7; 

es casi equivalente a:

const int val = 7; 

inicialización tan literal que está permitido para las variables const.

P.S .: Actualmente estoy estudiando Lippman's C++ Primer.

Respuesta

7

para que pueda escribir código como este:

void f(const string & s) { 
} 

f("foobar"); 

Aunque estrictamente hablando lo que realmente está sucediendo aquí no es la literal estar atado a una referencia constante - en su lugar se crea un objeto de cadena temprary:

string("foobar"); 

y esta cadena sin nombre está vinculada a la referencia.

Tenga en cuenta que en realidad es bastante inusual para crear variables de referencia de parámetros no como lo están haciendo - el propósito principal de las referencias es servir como parámetros de funciones y valores de retorno.

6

referencias constantes se pueden inicializar con literales y los temporales, ya que trivialmente les puede transformar a las variables explícitas:

int const& ans = 42; 
// tranformed: 
int __internal_unique_name = 42; 
int const& ans = __internal_unique_name; 

O cuando el curso de la vida no se extiende, como un parámetro de la función:

f("foobar"); 
// transformed: 
{ 
    string __internal_unique_name = "foobar"; 
    f(__internal_unique_name); 
} 

(Observe el bloque explícito en este caso.)

Si bien es posible hacer algo similar en el caso no constante, eso simplemente no es permitido en currents C++. C++ 0x (el siguiente estándar), sin embargo, tendrá referencias r-value.


Si no estaba claro, ref + 6 de su código crea un objeto temporal, que se puede visualizar como:

int const& ref = int(9); 
int const& another_ref = int(ref + 6); 

// transformed: 
int __A = 9; 
int const& ref = __A; 
int __B = ref + 6; 
int const& another_ref = __B; 

Esto puede ayudarle a entender/visualizar lo que está sucediendo, pero debe no escribir código real como este.También he usado nombres de subrayado dobles para ilustrar esos nombres, son detalles de implementación (utilizados por el compilador) y usted no los debe usar. Cualquier nombre que contenga guiones bajos adyacentes se reserva para la implementación de C++.

+0

+1. Pero creo que su segundo ejemplo se transformará en { cadena __internal_unique_name ("foobar"); f (__ internal_unique_name); } – mmmmmmmm

+0

@rstevens: no importa: la conversión no debe ser explícita, en cuyo caso son los mismos. –

2

Su código se reduce a la regla estándar de C++ donde la vida útil de un valor temporal está vinculada a la duración de la referencia const a la que está asignado. Consulte el artículo GoTWGotW #88: A Candidate For the “Most Important const” para obtener detalles adicionales.

Por ejemplo, la implementación ScopeGuard, descrita por Alexandrescu y Marginean en el artículo de Dr. Dobbs "Generic: Change the Way You Write Exception-Safe Code — Forever" depende de este comportamiento.

Cuestiones relacionadas