删除cout; 删除cin; 不要给出编译错误 - 标准库中的缺陷?

Naw*_*waz 14 c++ stream implicit-conversion c++11

以下是否会出现编译错误?

delete cout;
delete cin;
Run Code Online (Sandbox Code Playgroud)

答案是不.

它是标准库中流类实现的一个缺陷.它们具有以下要转换的转换函数void*,这意味着,所有流对象都可以隐式转换为void*:

operator void * ( ) const;
Run Code Online (Sandbox Code Playgroud)

这一般非常有用,因为它可以让我们在从文件读取输入时编写非常惯用的循环.但与此同时,它让用户可以写delete stream.正如我所说,您可以删除任何流对象.所以这些都是允许的:

delete ss;  //declare std::stringstream ss;
delete iss; //declare std::istringstream iss;
delete oss; //declare std::ostringstream oss;
Run Code Online (Sandbox Code Playgroud)

只有他们会发出警告,说(见ideone):

警告:删除'void*'未定义

你可以轻易地通过铸造来避免,比如说char*.但该程序仍然存在问题,并且在运行时很可能会崩溃.

-

所以我的问题是,在C++ 11中这个问题已得到解决和修复吗?以下文章提供了此问题的一个修复:

-

编辑:

来自@ Xeo对@ Alf答案的评论:

提出修复此问题的论文:

Che*_*Alf 18

它显然是固定的.

至少,在N3290中你有std::basic_ios::operator bool而不是那个void*转换,并且这operator bool是声明的explicit.

请注意,C++ 98/C++ 03不支持explicit类型转换运算符,但C++ 11 支持类型转换运算符.

一个explicit类型转换操作符

N3290§12.3.2/ 2;
仅被视为用户定义的直接初始化转换(8.5)

对于例如a 或语句中的条件,这似乎是不切实际的.whilefor

令人高兴的是,

N3290§4/ 3; 对于某些发明的临时变量(8.5),当且仅当声明格式正确时,
表达式e才能隐式转换为类型.某些语言结构要求将表达式转换为布尔值.对于某些发明的临时变量(8.5),当且仅当声明格式正确时,表示出现在这样的上下文中的表达被上下文转换为并且格式良好.隐式转换的效果与执行声明和初始化相同,然后使用临时变量作为转换的结果.TT t=e;teboolbool t(e);t

哪里bool t(e);直接初始化.

例如,您不必显式转换在a中用作条件的流对象while,因为隐式地存在显式转换(他是).

不幸的是,搜索N3290我找不到任何"某些语言结构"的列表,但是在对这个答案的评论中,JohannesD写道:

通过FDIS搜索"上下文",整个列表似乎是:if,while, do,for,noexcept,和static_assert条件; 第一个操作数?:; 的两个操作数&&||; 和.的操作数!.

干杯&hth.,

  • 是的,这是愚蠢的C++ 11"隐式明确".呵呵.:-) (5认同)
  • 它也已在核心语言方面得到修复.`delete`操作符现在只将转换函数视为指针到对象类型.因此,现在需要诊断,而不是具有未定义行为的情况.当然,这并不需要正式改变他的实施(他已经有了诊断),但很可能实施现在拒绝而不仅仅是警告...... (4认同)
  • 这是标准转换i子句4的一部分:"某些语言结构要求将表达式转换为布尔值.在这样的上下文中出现的表达式`e`被称为在上下文中转换为bool并且如果并且只有声明`bool t(e);`格式正确,对于一些发明的临时变量`t`.显然,Alf发现有趣的是"上下文转换"使用显式运算符来执行以前的隐式转换. (3认同)
  • 通过FDIS搜索"上下文",整个列表似乎是:`if`,`while`,`do`,`for`,`noexcept`和`static_assert`条件; `?:`的第一个操作数; "&&"和"||"的两个操作数; 以及`!`的操作数. (3认同)
  • 相关:[safe-bool成语是否过时?](http://stackoverflow.com/questions/6242768/is-the-safe-bool-idiom-obsolete). (2认同)