c++ - tipos - Comprueba si la referencia de flujo es NULL ya no se compila
tipos de errores en visual basic (3)
El código no compara la referencia con NULL
, sino que compara el objeto de referencia con NULL
. Las referencias no pueden ser NULL
, y es imposible comparar la referencia con NULL
.
Y
Este proyecto compilé i cuando lo usé hace mucho tiempo atrás con el antiguo gnu toolchain.
Porque el comportamiento cambió desde C ++ 11.
Antes de C ++ 11, std::ostream
podría convertirse implícitamente a void*
través del operador void * () , que devuelve un puntero nulo si se produce un error en la transmisión. Por lo tanto, la intención original del código es verificar si la transmisión no tiene errores.
Desde C ++ 11, la función de conversión se cambió al explicit operator bool()
, que devuelve false
si se produce un error. Tenga en cuenta que la función está declarada como explicit
, lo que significa que la conversión implícita a bool
no está permitida, por lo que el código no se compilará con C ++ 11 nuevamente porque std::ostream
no se puede convertir a bool
implícitamente (y luego se compara) con NULL
(un literal entero)).
Con un compilador compatible con C ++ 11 puede cambiar el código a
if (m_stream) {
m_stream.flush();
}
Tenga en cuenta que para las conversiones contextuales se consideran incluso las funciones de conversión explícitas. Para el código anterior, m_stream
se convertirá a bool
mediante explicit operator bool()
, entonces el valor se usaría para la condición de if
.
Estoy compilando un proyecto desactualizado con mis últimos compiladores gcc g ++, (versión> 6)
Hay una clase CodeWriter
con una variable de referencia ostream
.
class CodeWriter
{
//private:
protected:
ostream &m_stream;
public:
CodeWriter(ostream &stream):m_stream(stream){}
~CodeWriter(){
if(m_stream != NULL){
m_stream.flush();
}
}
};
La clase es bastante grande, así que solo incluí las variables y funciones relevantes.
Como puede ver, el destructor parece estar comparando la referencia con NULL
. Este proyecto se compiló bien cuando lo usé hace mucho tiempo con el antiguo gnu toolchain.
Pero ahora está lanzando un error que dice que no hay un operator !=
coincidente operator !=
Para comparar ostream
y long int
.
¿Alguien puede explicar la razón detrás del cambio y cómo puedo solucionarlo?
Estaré encantado de proporcionar información adicional / incluir a toda la clase si es necesario.
Las clases de flujo tenían un operator void*()
en una de las clases base en pre-C ++ 11. Por supuesto, el valor void*
podría compararse con NULL
.
En C ++ actual, en cambio, es un explicit operator bool()
que funciona en el contexto de la sentencia if
, pero no en una expresión general.
El uso de un void*
fue para evitar algunas conversiones no deseadas de bool
que ocurrían cuando no teníamos operadores explicit
.
Las transmisiones siempre se pueden evaluar en un contexto booleano, así que simplemente cámbielo a:
if (m_stream) {
m_stream.flush();
}
C ++ 11 hizo la conversión a bool explicit
. Esto es equivalente a if (!m_stream.fail())
. Antes de C ++ 11, esta capacidad de comprobación a corto plazo se logra al proporcionar una conversión (implícita) a void*
, por lo que su código anterior solía funcionar.
La razón por la que el código está verificando esto, en lugar de simplemente llamar a m_stream.flush();
directamente, es posible que la secuencia pueda tener excepciones habilitadas para fallas y que puedan lanzar, [actualizar:] pero, como señaló @Arne, la flush
sí misma puede fallar y lanzar también. Si no hay excepciones, solo puede omitir la verificación booleana por completo. [/ Actualizar]