2012-02-29 28 views
6

¿Por qué es la salida del siguiente programa simplemente int3 y no int3&4?constructor de copia con parámetros por defecto nunca se llama

#include <iostream> 

class B 
{ 
public: 
    explicit B(int i) { std::cout<<"int"<<i; } 
    B(const B& rhs, int i = 0) { std::cout<<"&"<<i; } 
}; 

int main(int, char**) 
{ 
    B b(B(3), 4); 
} 

Comando: clang++ test.cpp -O0

Compilador: Apple versión 3.0 sonido metálico (etiquetas/de Apple/ruido metálico-211.12) (basado en LLVM 3.0svn)

+0

Imprime 'int3 & 4' para mí (GCC 4.6.2,' -O3'). –

+0

En realidad, mi g ++ 4.6.1 imprime "int3 y 4". – Duck

+1

+1 para el caso de prueba corto y completo. http://sscce.org –

Respuesta

1

Este fue un bug in clang, que tiene since been fixed. Copy-elision se estaba aplicando incorrectamente a la llamada del constructor, porque clang no estaba verificando cuántos argumentos se proporcionaron antes de concluir que se trataba de una copia.

La solución estará en la próxima versión de clang 3.1.

3

Parece que podría haber encontrado un capricho del compilador:)

Si cambia de versión del compilador para cualquier cosa que no es LLVM 3.0, la salida se int3 & 4.

Esta impresora i nt3 & 4 en LLVM 3.0, por lo que parece estar relacionado con el hecho de que B (3) es un objeto temporal:

class B 
{ 
public: 
    explicit B(int i) 
    { 
     std::cout<<"int"<<i; 
    } 
    B(const B& rhs, int i = 0) 
    { 
     std::cout<<"&"<<i; 
    } 
}; 

int main(int, char**) 
{ 
    B a(3); 
    B b(a, 4); 
} 
+0

Sí, esto fue un error en clang, que desde entonces se ha corregido. Copy-elision se estaba aplicando incorrectamente a la llamada del constructor, porque clang no estaba verificando cuántos argumentos se proporcionaron antes de concluir que se trataba de una copia. –

+0

@RichardSmith ¿Puedes publicar este comentario como respuesta? –

0

Lo más probable es RVO y NRVO comieron su código. Estas condiciones especiales le permiten al compilador eliminar silenciosamente las copias de objetos que de otro modo serían impuestas por el lenguaje. Como nunca se realizó una copia como resultado, el código nunca imprime la declaración en el constructor de copia.

+0

¿Se permitirían RVO y NRVO incluso en modo Depuración? Tal como lo entiendo, son optimizaciones y, por lo tanto, deberían deshabilitarse cuando se ejecuta en modo Debug, pero en el modo Depuración, también recibo "int3", en LLVM 3.0 – Carl

+0

. Sólo pensé en agregar esto: http://stackoverflow.com/ preguntas/8556608/what-can-i-razonablemente-expect-a-compiler-to-be-able-to-inline. Aparentemente, algunos compiladores también implementan RVO y/o NRVO de forma selectiva en el modo de depuración, lo que explicaría el comportamiento de LLVM. – Carl

+0

@carleeto: el compilador puede hacerlo legalmente cuando quiera. – Puppy

Cuestiones relacionadas