我正在用我最新的gcc g ++编译器编译一个过时的项目,(版本> 6)
有一个CodeWriter
带ostream
引用变量的类.
class CodeWriter { //private: protected: ostream &m_stream; public: CodeWriter(ostream &stream):m_stream(stream){} ~CodeWriter(){ if(m_stream != NULL){ m_stream.flush(); } } };
这个类非常大,所以我只包含了相关的变量和函数.
正如您所看到的,析构函数似乎是在比较引用NULL
.当我用旧的gnu工具链使用它时,这个项目编译得很好.
但现在它抛出一个错误,说没有匹配operator !=
比较ostream
和long int
.
任何人都可以解释改变背后的理由,以及我如何解决这个问题?
如果需要,我很乐意提供更多信息/包括全班.
代码不是将引用本身与之NULL
比较,而是将引用对象与之进行比较NULL
.引用NULL
不可能,并且不可能将引用本身与之比较NULL
.
和
当我用旧的gnu工具链使用它时,这个项目编译了我.
因为自C++ 11以来行为发生了变化.
C++ 11之前,std::ostream
可被隐式转换为void*
经由操作者无效*() ,它返回一个空指针,如果在流错误发生.所以代码的初衷是检查流是否没有错误.
从C++ 11开始,转换函数被更改为explicit operator bool()
,false
如果发生错误则返回.注意函数被声明为explicit
,这意味着bool
不允许隐式转换为,所以代码不会再次使用C++ 11编译,因为std::ostream
无法bool
隐式转换(然后与NULL
(整数文字)进行比较) .
使用兼容C++ 11的编译器,您只需将代码更改为
if (m_stream) { m_stream.flush(); }
请注意,对于上下文转换,甚至会考虑显式转换函数.对于上面的代码,m_stream
将转换为bool
via explicit operator bool()
,然后该值将用于条件if
.
可以始终在布尔上下文中评估流,因此只需将其更改为:
if (m_stream) { m_stream.flush(); }
C++ 11转换为bool explicit
.这相当于if (!m_stream.fail())
.在C++ 11之前,这种简短的可检查性是通过提供(隐式!)转换来实现的void*
,这就是您的旧代码以前工作的原因.
代码检查这个而不是直接调用的m_stream.flush();
原因可能是流可能有异常启用失败而且可能抛出,[update:]但是,正如@Arne指出的那样,flush
它本身也可能失败并抛出.如果没有异常,你可以完全跳过布尔检查.[/ update]
流类operator void*()
在pre-C++ 11中有一个基类.当然,void*
价值可以与之比较NULL
.
在当前的C++中,这是explicit operator bool()
在if
语句的上下文中工作的,而不是在一般表达式中.
使用a void*
是为了避免bool
在我们没有explicit
运营商时发生的一些不必要的转换.