studio - Posible error en el manejo de la palabra clave `default` en VS2015 C++
visual studio 2015 paquetes (1)
Mientras probaba el compilador VS2015 C ++, encontré un error extraño con la palabra clave default
. Si lo hago:
struct Dummy
{
Dummy() = default;
Dummy(const Dummy &) = delete;
};
int main()
{
const Dummy& ref = Dummy();
return 0;
}
yo obtengo
error C2280: ''Dummy :: Dummy (const Dummy &)'': intentando hacer referencia a una función eliminada
nota: ver declaración de ''Dummy :: Dummy''
Pero si uso un constructor vacío
struct Dummy
{
Dummy() {}
Dummy(const Dummy &) = delete;
};
int main()
{
const Dummy& ref = Dummy();
return 0;
}
El código compila. Ejecutar el primer ejemplo con g++ o clang no produce ningún error.
¿Por qué utilizar el constructor predeterminado con VS2015 intenta usar el constructor de copia donde no lo hace en g ++ o clang?
Definitivamente es un error en VS 2015.
En C ++ 11, la asignación de una referencia temporal a una constante no debe llamar al constructor de copia, pero VS 2015 lo hace.
Puedes comprobarlo con
#include <iostream>
struct Dummy
{
Dummy() = default;
Dummy(const Dummy &) { std::cout << "copy ctor" << std::endl; }
void test() const { std::cout << "test" << std::endl; }
};
int main()
{
const Dummy& ref = Dummy();
ref.test();
return 0;
}
compilado en VS 2013, 2015, gcc y clang. Solo VS (cualquier versión) llama al constructor de copia, si el constructor de la clase se define como = default
.
Creo que el compiiler VS aún en 2015 usa erróneamente las antiguas reglas estándar de C ++ 03 para esto (8.5.3.5 de C ++ 03):
Si la expresión de inicialización es un rvalor, con T2 un tipo de clase, y "cv1 T1" es compatible con "cv2 T2", la referencia se enlaza de una de las siguientes maneras (la opción está definida por la implementación):
- La referencia está vinculada al objeto representado por el valor r (ver 3.10) o a un subobjeto dentro de ese objeto.
- Se crea un temporal de tipo "cv1 T2" [sic], y se llama a un constructor para copiar todo el objeto rvalue en el temporal. La referencia está vinculada a lo temporal o a un subobjeto dentro de lo temporal.
El constructor que se usaría para hacer la copia será llamable, ya sea que la copia se haga o no.
Los desarrolladores de VS eligieron la segunda vía. Corrigieron esto para el constructor vacío definido por el usuario ( {}
), pero se olvidaron de hacer esto para los constructores predeterminados ( = default
).
PD. Error en MS Connect (por favor vote)