下面会出现编译错误吗?
delete cout;
delete cin;
答案是:不。
这是标准库中流类实现中的一个缺陷。它们具有以下到 void*
类型,这意味着所有流对象都可以隐式转换为 void*
:
operator void * ( ) const;
这通常非常有用,因为它让我们可以编写 非常惯用的循环,例如,在阅读时从文件输入。但同时,它允许用户编写删除流
。正如我所说,您可以删除任何流对象。所以所有这些都是允许的:
delete ss; //declare std::stringstream ss;
delete iss; //declare std::istringstream iss;
delete oss; //declare std::ostringstream oss;
只是他们会发出警告,说(参见 ideone):
警告:删除“void*”未定义
,您可以轻松避免只需将其强制转换为字符*
。但程序仍然存在问题,运行时很可能会崩溃。
--
所以我的问题是,这个问题在 C++11 中是否已得到解决和修复?以下文章提供了解决此问题的方法:
-
编辑:
来自 @Xeo 对 @Alf 的回答的评论:
提出解决此问题的论文:
Will the following give a compilation error?
delete cout;
delete cin;
The answer is : No.
It is a flaw in the implementation of stream classes from the Standard library. They have the following conversion function to void*
type, which means, all stream objects can be implicitly converted to void*
:
operator void * ( ) const;
This is very useful in general as it lets us write very idiomatic loop, say, when reading input from files. But at the same time, it lets user to write delete stream
. As I said, you can delete any stream object. So all of these are allowed:
delete ss; //declare std::stringstream ss;
delete iss; //declare std::istringstream iss;
delete oss; //declare std::ostringstream oss;
Only that they'll give a warning, saying (see at ideone):
warning: deleting ‘void*’ is undefined
which you can easily avoid just by casting, say, tochar*
. But the program has still issue, and most likely will crash when running it.
--
So my question is, has this issue been addressed and fixed, in C++11? The following article provides one fix for this problem:
--
Edit:
From @Xeo's comment on @Alf's answer:
The paper which proposed a fix for this issue:
发布评论
评论(2)
它显然已经被修复了。
至少,在 N3290 中,您有
std::basic_ios::operator bool
而不是void*
转换,并且此operator bool
声明为 <强>明确
。请注意,C++98/C++03 不支持显式类型转换运算符,但 C++11 支持。
显式
类型转换运算符对于
while
或for
语句中的条件来说,这似乎不切实际。令人高兴的是,
其中
bool t(e);
是直接初始化。例如,您不必显式转换在
while
中用作条件的流对象,因为存在隐式显式转换(呵呵)。不幸的是,搜索 N3290 我找不到发生这种情况的“某些语言结构”的任何列表,但在对此答案的评论中 JohannesD 写道:
干杯&呵呵,,
It has apparently been fixed.
At least, in N3290 you have
std::basic_ios::operator bool
instead of thatvoid*
conversion, and thisoperator bool
is declaredexplicit
.Note that C++98/C++03 did not support
explicit
type conversion operators, but C++11 does.An
explicit
type conversion operatorAnd that might seem to be impractical for the condition in e.g. a
while
orfor
statement.Happily,
where
bool t(e);
is a direct-initialization.E.g. you don’t have to explicit convert a stream object used as condition in a
while
, because there is implicitly an explicit conversion (he he).Unfortunately, searching N3290 I can’t find any list of the “certain language constructs” where this happens, but in comments to this answer JohannesD wrote:
Cheers & hth.,
如果我能给出 2 美分的话,我认为标准库有点“缺陷”,尽管意图是好的。
引入了
operator void*()
来允许类似的代码while(stream)
或if(!stream)
或while(stream && ...)
,而不给予隐式访问整数算术(operator bool
应该给出的)。事实上,这会禁用整数运算,但可以访问指针功能(例如删除...)。
现在,在 C++0x 中,引入了显式 oeprator bool() 。它不会隐式地提供对任何功能的访问,因为它需要隐式转换。但是...等一下:'while(bool(stream))' 甚至
while(static_cast(stream))
太罗嗦了...操作员 !是明确的,并且
'while(!!stream)' 看起来非常有效,我什至想知道为什么不接受它作为范例:
如果我想要将某些内容显式转换为 bool,我只需提供一个
operator!()
并赋予
!
“无效”的含义和!!
“有效”的含义。比隐式转换安全得多,而且不是无用的冗长:毕竟
!
一直存在!If I can give my 2 cents, I think the standard library "flawed" a bit, with all the good intentions.
The
operator void*()
had been introduced to allow code likewhile(stream)
orif(!stream)
orwhile(stream && ...)
, without giving an implicit access to integer arithmetic (thatoperator bool
whould have given).In fact, this disable integer arithmetic, but gives access to pointer features (like delete ...).
Now, in C++0x, an
explicit oeprator bool()
had been introduced. It doesn't implicitly give access to whatever feature, since it requires an implicit conversion. But ... wait a bit: 'while(bool(stream))' or evenwhile(static_cast<bool>(stream))
are so wordy...Operator ! is explicit, and
'while(!!stream)' looks so effective that I even wonder why not accept this as a paradigm:
If I want something to be explicitly converted into bool, I just provide an
operator!()
and give to
!
the memaning of "is not valid" and of!!
as "is valid".Much safer then an implicit conversion and not uselessly wordy: after all
!
exist from ever!