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

发布于 2024-12-05 10:55:06 字数 1564 浏览 0 评论 0 原文

下面会出现编译错误吗?

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:

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

千秋岁 2024-12-12 10:55:06

它显然已经被修复了。

至少,在 N3290 中,您有 std::basic_ios::operator bool 而不是 void* 转换,并且此 operator bool 声明为 <强>明确

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

显式类型转换运算符

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

对于 whilefor 语句中的条件来说,这似乎不切实际。

令人高兴的是,

N3290 §4/3;
当且仅当声明 T t=e; 时,表达式 e 可以隐式转换为类型 T对于一些发明的临时变量t(8.5)来说,格式良好。某些语言结构要求将表达式转换为布尔值。
出现在这种上下文中的表达式e被称为根据上下文转换为bool,并且当且仅当声明t (8.5),>bool t(e); 格式良好。任一隐式转换的效果与执行以下操作相同
声明和初始化,然后使用临时变量作为转换的结果。

其中 bool t(e);直接初始化

例如,您不必显式转换在 while 中用作条件的流对象,因为存在隐式显式转换(呵呵)。

不幸的是,搜索 N3290 我找不到发生这种情况的“某些语言结构”的任何列表,但在对此答案的评论中 JohannesD 写道:

在 FDIS 中搜索“contextually”,整个列表似乎是:ifwhile >,
dofornoexcept 和 < strong>static_assert 条件; ?: 的第一个操作数;两个都
&&|| 的操作数;和 ! 的操作数。

干杯&呵呵,,

It has apparently been fixed.

At least, in N3290 you have std::basic_ios::operator bool instead of that void* conversion, and this operator bool is declared explicit.

Note that C++98/C++03 did not support explicit type conversion operators, but C++11 does.

An explicit type conversion operator

N3290 §12.3.2/2;
is only considered as a user-defined conversion
for direct-initialization (8.5)

And that might seem to be impractical for the condition in e.g. a while or for statement.

Happily,

N3290 §4/3;
An expression e can be implicitly converted to a type T if and only if the declaration T t=e; is well-formed, for some invented temporary variable t (8.5). Certain language constructs require that an expression be converted to a Boolean value.
An expression e appearing in such a context is said to be contextually converted to bool and is well-formed if and only if the declaration bool t(e); is well-formed, for some invented temporary variable t (8.5). The effect of either implicit conversion is the same as performing the
declaration and initialization and then using the temporary variable as the result of the conversion.

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:

Searched through the FDIS for “contextually”, and the whole list seems to be: if, while,
do, for, noexcept, and static_assert conditions; the first operand of ?:; both
operands of && and ||; and the operand of !.

Cheers & hth.,

祁梦 2024-12-12 10:55:06

如果我能给出 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 like
while(stream) or if(!stream) or while(stream && ...), without giving an implicit access to integer arithmetic (that operator 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 even while(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!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文