【问题标题】:why is std::cout convertible to void* if using g++?如果使用 g++,为什么 std::cout 可以转换为 void*?
【发布时间】:2015-01-21 05:31:12
【问题描述】:

为什么可以将std::ostream 转换为void 指针?我不知道std::ostream 中有任何此类转换运算符。代码如下

#include <iostream>

int main()
{
    void *p = std::cout; // why does this work? 
}

我之所以问这个问题,是因为我看到一个放置操作符 new 被调用为

Foo* pFoo = new (std::cerr) Foo;

完全不知道为什么要写这样的东西。

PS:我正在使用 g++ 4.9.2 进行编译,带或不带 -std=c++11。 clang++ 不接受代码

PSS:发现由于所谓的“安全布尔问题”(参见@nicebyte 的答案),在 C++11 之前,为 std::ostream 定义了一个 void* 转换运算符,然后在 C 中将其删除++11。但是,我的代码使用 g++ 在 C++11 中编译得很好。更重要的是,无论我使用什么版本的标准,clang++ 都会拒绝它,即使使用-std=c++98,尽管我的理解是如果编译为 pre-C++11,它应该接受。

【问题讨论】:

  • new (std::cerr) Foo ?什么。这。地狱。
  • @Quentin :) 当我看到它时,我就是这么告诉自己的。
  • 如果你能提供来源,我会很高兴的。我只能想到这可能导致的可怕事情。
  • 在 Scott Meyers 的书“Effective C++”,第 52 项,第 291 页(第 3 版)中
  • 今天我学到了一些东西,谢谢!这肯定是一个奇怪的小动物......

标签: c++ pointers implicit-conversion ostream


【解决方案1】:

阅读this(您的问题已在最后一节“安全布尔问题”中得到解答)。

详细说明一下,该实现定义了对 void* 的隐式转换,为 std::cinstd::cout 之类的事物定义,这样 while(std::cin&gt;&gt;x){...} 之类的代码就可以编译,而 int x = std::cin; 之类的代码则没有。它仍然存在问题,因为您可以编写示例中的内容。

C++11 通过引入显式转换解决了这个问题。

显式转换运算符如下所示:

struct A {
 explicit operator B() { ... } // explicit conversion to B
};

当 A 显式转换为 B 时,这样的代码就变得合法了:

A a;
B b(a);

但是,这样的代码不是:

A a;
B b = a;

if(std::cin) 这样的构造需要将cin 转换为bool,标准规定为了使转换在特定情况下有效,像bool x(std::cin); 这样的代码应该是“合法的”。这可以通过向bool 添加显式转换来实现。它允许在上述上下文中使用 cin/cout,同时避免使用 int x = std::cout; 之类的东西。

如需了解更多信息,请参阅Bjarne's pagethis question

【讨论】:

  • 我已经编辑了我的答案以提供更多详细信息(还包括有关 C++11 的信息)。
  • @nicebyte,谢谢,知道显式运算符,但不知道std::ostream 有一个void* 转换运算符。然而,在 C++11 中,由于引入了对bool 的显式转换,似乎消除了这种void* 转换。然而,即使在g++ 中使用-std=c++11,我的代码仍然有效,所以我猜这是 libstdc++ 实现中的一个缺陷。在clang++中,即使我使用-std=c++98,代码仍然无法编译。
  • 我不认为标准明确规定必须实现 cin/cout 以使用显式转换为 bool。也可能是因为一些奇怪的向后兼容性考虑,g++ 留在了隐式 void* 转换中。
  • @nicebyte:很好的答案。感谢您在您的回答中提供 cppreference 链接。
【解决方案2】:

只回答后续问题,因为 nicebyte 的回答非常适合原始问题。

很有可能,您的 gcc 设置为使用 libstdc++(由于它是一个破坏 ABI 的更改,因此尚未更改运算符),并且您的 clang 设置为使用 libc++(从一开始就打算作为一个 C++11 标准库,在 C++98 模式下不太符合 - 它提供了一个在 C++11 中显式的 bool 转换运算符。

【讨论】:

    【解决方案3】:

    我认为这是允许 if (std::cout) ... 而不允许隐式转换为 bool 或类似的东西。

    【讨论】:

    • IIRC,这个答案出现在低质量帖子审核队列中。我将其归类为不是答案,因为使用了我认为类似的东西,对我来说它看起来像是评论,而不是回答。但我不懂 C++,如果这是一个有效的答案并且标记它是错误的,我很抱歉。
    猜你喜欢
    • 2021-11-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多