2010-11-27 30 views
10

Considere el código dadollamada al constructor de copia

struct ABC 
{ 
    ABC() 
    { 
     std::cout<<" Calling from default constructor"; 
    } 

    ABC(const ABC &copy) 
    { 
     std::cout<<"Calling from copy constructor"; 
    } 
}; 

int main() 
{ 
    ABC abc = ABC(); 
} 

Tengo dos preguntas


Q1) Extracción const de la declaración de parámetros constructor de copia da error. ¿Por qué?

Q2) Después de agregar la palabra clave const, no veo una llamada al constructor de copia. ¿Por qué? El constructor de copia no recibe llamadas, entonces, ¿por qué es necesario const?


TIA

+0

Agregaría Q3) ¿Por qué no se muestra nada después de que cambiamos esa línea a 'ABC abc (ABC());'? – Kos

+2

Respuesta a (Q3) [aquí] (http://stackoverflow.com/questions/4283576/constructor-invocation-mechanism/4283589#4283589). Respuestas a Q1 y Q2 [aquí] (http://stackoverflow.com/questions/4286301/why-isnt-the-copy-constructor-called-here/4286330#4286330) –

+0

@Prasoon: Q1 no se responde en el enlace publicaste – ybungalobill

Respuesta

5
  1. Se necesita el constante porque intenta inicializar ABC ABC con un temporal() que es const. Por lo tanto, si el constructor no es const el compilador debe rechazar el código.

  2. Después de hacerlo, el código es una queja estándar y el compilador puede compilarlo. Sin embargo, está permitido optimizar la copia en este caso como se dice en el estándar, por lo que elimina la llamada al constructor de copia.

+0

@ybungalobill: El compilador no genera constructores de copia en todos los escenarios, incluso si no escribes explícitamente uno que coincida con el firma exactamente. No puedo recordar las reglas, pero no siempre se generan. – Puppy

+0

@DeadMG: ¿Quién dijo que siempre se generan? De Verdad? ¿Cuál es la conexión? No se generan cuando no se pueden generar (como cuando tienes clases base o miembros sin el constructor de copia, etc.). El constructor de copia se genera en este ejemplo. – ybungalobill

+2

Se equivoca sobre el constructor de copia predeterminado: "Un constructor que no es de plantilla para la clase' X' es un constructor de copia si su primer parámetro es de tipo 'X &', 'const X &', 'volátil X y' o 'const volátil X & ', y o bien no hay otros parámetros o todos los otros parámetros tienen argumentos predeterminados" – UncleBens

1

Si también define el operador de asignación verá que ni siquiera uno que se llama: compilador optimiza ABC abc = ABC(); en ABC abc;, ya que tienen la misma semántica.

Sobre la otra duda, G ++ no se queja de declarar el parámetro constructor de copia como no const (ni siquiera con -Wall -W -std=c++98). No revisé el estándar sobre esto de todos modos.

+0

Olvidaste '--pedantic ', pero tampoco cambia nada. Pero no es realmente sorprendente: ¿por qué no permitir tener un constructor de copia solo para objetos no const en algunos casos? O diferentes constructores de copia para const y non-const? – Kos

2

La const es necesaria ya que no está permitido vincular una referencia temporal a una referencia no constante. Aunque el compilador optimiza el constructor de copias, no es hasta una etapa posterior.

El estándar C++ 0x está abordando esto con la adición de referencias rvalue. lo que permitiría que usted deje caer el parámetro const a un no-const ...

ABC(ABC&& copy) 

Aunque usted todavía desea que el constructor de copia regular de referencia ...

+0

+1 por mencionar eso; Eso se llama el "constructor de movimiento", supongo. – Kos

+0

@kos: muchas veces sí, pero nada indica que deba seguir la semántica de movimiento (es decir, dejar el objeto original en un estado construido por defecto), de modo que si solo quiere copiar la semántica para los temporales, entonces esto también funciona. – diverscuba23

3

Q1) const Extracción de la copia declaración de parámetro constructor da error. ¿Por qué?

ABC abc = ABC(); 

es equivalente a

ABC abc((ABC())); 

Puesto que usted está pasando un temporal al constructor de copia, sólo se puede obligar a las referencias const, las referencias no no const.

Un constructor de copia puede tomar referencias que no sean const (por ejemplo, std::auto_ptr), pero esto significa que su uso es más restringido.

Q2) Después de añadir la palabra clave const I no veo una llamada a la copia constructor. ¿Por qué? El constructor de copia no recibe llamadas, entonces, ¿por qué es necesario el const ?

En el escenario dado, el compilador puede optimizar las llamadas redundantes al constructor de distancia. ¿Por qué crear un objeto predeterminado solo para copiarlo, si solo pudiera invocar el constructor predeterminado solo?

Sin embargo, incluso si las llamadas para copiar el constructor están optimizadas, el compilador debe verificar que el código sea válido tal como está escrito, como si la construcción de la copia no hubiera sido optimizada.

Cuestiones relacionadas