如果使用g ++,为什么std :: cout可以转换为void*?

vso*_*tco 13 c++ pointers ostream implicit-conversion

为什么一个能投射出std::ostreamvoid指针?我不知道有任何这样的转换运算符std::ostream.代码如下

#include <iostream>

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

我问这个问题,因为我已经看到new调用了一个放置操作符

Foo* pFoo = new (std::cerr) Foo;
Run Code Online (Sandbox Code Playgroud)

并且完全不知道为什么会写这样的东西.

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

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

nic*_*yte 11

阅读本文(您的问题在最后一节回答" 安全布尔问题 ").

要详细一点,落实定义隐式转换void*的东西像定义std::cinstd::cout,只是让这样的代码while(std::cin>>x){...}编译,而类似的代码int x = std::cin;没有.它仍然存在问题,因为你可以像你的例子那样写东西.

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

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

struct A {
 explicit operator B() { ... } // explicit conversion to B
};
Run Code Online (Sandbox Code Playgroud)

当A有明确的B转换时,这样的代码变得合法:

A a;
B b(a);
Run Code Online (Sandbox Code Playgroud)

但是,像这样的代码不是:

A a;
B b = a;
Run Code Online (Sandbox Code Playgroud)

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

有关更多信息,请参阅Bjarne的页面以及此问题.