C ++流类中有转换函数 operator void*() const
。这样所有流对象都可以隐式转换为void*
。在与SO的程序员交互过程中,他们建议我不要使用void*
,除非你有充分的理由使用它。 void*
是一种消除类型安全的技术。错误检查。因此,由于该转换功能存在以下程序完全有效。这是C++ standard library.
#include <iostream>
int main()
{
delete std::cout;
delete std::cin;
}
查看实时演示here.
上述程序在C ++ 03中有效,但在C ++ 11&amp;以后的编译器,因为这个转换函数被删除了。但问题是,如果它是危险的,它是C ++标准库的一部分?允许将流对象转换为void*
的目的是什么?有什么用?
答案 0 :(得分:25)
std::stringstream
的一项功能是,如果该流用作bool
,则如果该流仍然有效且true
,则会转换为false
如果不是。例如,如果您实现自己的lexical cast版本,则可以使用简单的语法。
(作为参考,boost
包含一个名为lexical_cast
的模板函数,它执行类似于以下简单模板函数的操作。)
template <typename T, typename U>
T lexical_cast(const U & u) {
T t;
std::stringstream ss;
if (ss << u && ss >> t) {
return t;
} else {
throw bad_lexical_cast();
}
}
例如,如果您在不允许例外的项目上工作,您可能希望改为使用以下版本。
template <typename T, typename U>
boost::optional<T> lexical_cast(const U & u) {
T t;
std::stringstream ss;
if (ss << u && ss >> t) {
return t;
} else {
return boost::none;
}
}
(上面有各种方法可以改进,这段代码只是举个例子。)
以上使用operator void *
如下:
ss << u
会返回对ss
。ss
隐式转换为void *
,如果流操作失败则为nullptr
,如果流仍然良好则为非空。&&
运算符快速中止,具体取决于该指针的真值。ss >> t
运行,并返回并转换为void *
。t
。如果失败,那么我们发出错误信号。bool转换功能基本上只是语法糖,可以简洁地编写这个(以及许多其他内容)。
实际引入隐式bool转换的缺点是,std::stringstream
可隐式转换为int
以及许多其他类型,因为bool
可隐式转换为int
}。这最终导致其他地方的语法噩梦。
例如,如果std::stringstream
进行了隐式operator bool
转换,请假设您拥有以下简单代码:
std::stringstream ss;
int x = 5;
ss << x;
现在处于重载分辨率,你有两个潜在的重载要考虑(!),正常的一个operator<<(std::stringstream &, int)
,以及ss
转换为bool
的那个,然后提升为int
,并且位移运算符可能会应用operator<<(int, int)
,因为隐式转换为bool
...
解决方法是使用隐式转换为void *
,可以在上下文中用作bool,但实际上不能隐式转换为bool或int。
在C ++ 11中,我们不再需要这种解决方法,并且没有理由任何人明确使用void *
转换,因此它只是被删除了。
(我正在搜索引用,但我相信此函数的值仅指定为nullptr
时的值,而不是nullptr
时的值,并且它是实现定义了它可能产生的非零指针值。所以任何依赖于void *
版本并且不能轻易地重构以使用bool
版本的代码都是不正确的。)
void *
解决方法仍然没有问题。在提升中,为C ++之前的代码开发了一个更复杂的“安全bool”习惯,其中iiuc基于类似T*
的内容,其中T
是“类型使用过一次”,如在实现该习惯用法的类中定义的结构,或者使用该类的指向成员函数并使用返回值(该类是该类的特定私有成员函数或nullptr)。例如,在所有的boost智能指针中都使用了“安全bool”习语。
无论如何通过引入explicit operator bool
在C ++ 11中清理整个混乱。
答案 1 :(得分:11)
这是C ++标准库中的一个缺陷。
是C ++标准库旧版本(1998年和2003年)的一个缺陷。 2011年及以后版本的标准中不再存在此缺陷。我们在语言中添加了一项新功能,即将转化运算符标记为explicit
,以使转化运算符安全bool
。
原始版本的C ++标准的开发人员明确选择使用转化为void*
而不是转换为bool
,因为非显式转换为bool
非常不安全在很多方面。相比之下,虽然operator void*()
显然很明显,但它起作用,至少只要你没有将指针强加给其他东西或试图删除它。 (替代方案operator!
可以说比任何一个转换运算符更安全,但这需要非直观和深奥的while (!!stream) {...}
。)
&#34;安全布尔的概念&#34; idiom是在原始的1998/1999版标准发布后开发的。它是否在2003年之前开发有点无关紧要;该标准的2003版本旨在成为该原始标准的错误修复。那个operator void*()
让delete std::cin
编译并没有被视为一个错误,而不是那么做,然后才能做到这一点。&#34;有点问题。
&#34;安全布尔&#34;成语表明确实存在使operator bool()
安全的替代方案,但是如果你看看任何一个实现,它们都是大规模的复杂和大规模的kludgy。 C ++ 11解决方案非常简单:允许转换运算符使用explicit
关键字进行限定。 C ++ 11解决方案删除了void*
转换运算符,并添加了explicit bool
转换运算符。这使得&#34;安全的布尔&#34; idiom已经过时,至少只要您使用符合C ++ 11(或更高版本)的编译器。