2011-11-02 14 views
23

El entrevistador me mostró un código como este y me preguntó si se compilaría, y daría mi razonamiento. Le dije con toda certeza que no compilaría, porque 10 es una constante y no se puede asignar una constante a una referencia no constante (como int & b = 10 no se compilará), también, _a es una variable temporal y es también se considera const, de nuevo, no se puede usar la referencia no constante para referir una variable const.¿Por qué compila esto? Esperando "no se puede asignar una constante a una referencia no const"

Sin embargo, después de llegar a casa para mi sorpresa, me pareció compilar perfectamente con todos los compiladores posibles. Además, no conseguí el trabajo. ¿Qué parte de mi entendimiento salió mal?

class A { 
    int& a; 
public: 
    A(int _a):a(_a) {} 
}; 

int main() { 
    A a(10); 
}  
+24

¿Cuál era el puesto para el que estaba entrevistando? Si es algo más que construir un analizador de C++, diría que probablemente sea ridículo tener que conocer cada rincón oscuro de C++ como este. – Mysticial

+11

Tengo la impresión de que los entrevistadores ponen demasiado énfasis en conocer los rincones oscuros del idioma y no lo suficiente en las habilidades de diseño y mejores prácticas. –

+1

@Mysticial: este es un escollo común para los nuevos desarrolladores ya que este código parecerá funcionar al principio pero fallará en un punto aleatorio (después de una llamada a la función). – Dani

Respuesta

27

no hay una "cesión" de un const con este código ...

El código llama al constructor que toma un int ya su vez llama a la inicialización del int&. Se saltó varios pasos que el compilador ve/toma cuando asumió que significaba int& b = 10, mientras que es más como _a = 10; int& a = _a;. compila pero obviamente no es nada que quieras usar (vinculando una referencia a la pila que luego conducirá a un comportamiento/corrupción indefinida) ...

7

Esto se enlazará a la pila, porque los argumentos de la función pueden ser atados por referencia. sin embargo, esto no es seguro en absoluto y causará un comportamiento indefinido y acumulará corrupción en algún momento.

12

_a es una variable temporal y también se considera constante,

incorrecto. En el ámbito del cuerpo del constructor y la lista de inicializadores, no es temporal en absoluto. Es un argumento de valor y función: dura mucho más allá de su único uso para todo el cuerpo de la función.

Además, rvalues ​​y const no tienen absolutamente nada que ver entre sí, excepto que en C++ 03 no se pueden enlazar referencias no constantes con valores r. Por ejemplo, puede llamar a muchas funciones no const en rvalues ​​simplemente bien.

Este código es directamente equivalente a

int main() { 
    int i = 10; 
    int& x = i; 
} 

Con la mayor diversión de los problemas de toda la vida involucradas con él estar en una clase.

4

Hay 2 preguntas de este problema.

q1) si se debe compilar o no?

Res: se compilará porque aquí a se refiere a _a, no es dolor de cabeza del compilador cómo _a obtendrá datos.

q2) ¿Es correcto el código? Quiero decir si habrá algún error de tiempo de ejecución o no?

Resp: Este no es el código correcto. Aquí a se refiere a _a que es la variable de pila. Entonces, si accedes a la variable de referencia usando un objeto clase A, la salida será impredecible. permite echar un ejemplo como se indica a continuación:

class A { 
public: 
    int& a; 

    A(int _a):a(_a) {} 
}; 

int main() { 
    A a(10); 
    A a1(11); 
    cout << a.a; 
}  

ver la salida.La salida es impredecible porque está intentando acceder a la variable de referencia a, que hace referencia a la variable de pila del constructor

Cuestiones relacionadas