问题 为什么在流输出中


今天我在我的程序中输入了一个小错误,并且为什么我没有得到任何输出而徘徊,尽管程序编译得很好。基本上它减少到这个:

#include <iostream>

int main()
{
    std::cout < "test"; // no << but <
}

我完全不知道在这里执行了什么样的隐式转换,因此程序仍然可以编译(g ++ 4.9.2甚至g ++ 5)。我刚刚意识到clang ++拒绝代码。有转换吗? void* 被执行(想不出别的什么)?我记得看过这样的东西,但我认为它是用g ++ 5解决的,但事实并非如此。

编辑: 我没有编译 -std=c++11,所以代码在pre-C ++ 11中有效(由于转换为 void* 的 ostream)。编译时 -std=c++11 g ++ 5拒绝代码,g ++ 4.9仍然接受它。


7700
2018-04-18 22:06


起源

我收到了g ++ 4.9.2关于未使用的计算值的警告 -Wall 虽然。 - Raphael Addile
@Raphael确实,当我编译时我没有看到所有的警告,现在我看到并意识到发生了什么,虽然要说它有点不寻常。我大部分时间都在使用 -Wall然而,这是我在崇高文本中编译的一小段代码,并实现了它神奇地起作用 - vsoftco
为什么 这个 给出0作为输出? - Destructor
@Destructor因为你最终比较了两个指针: (void*)std::cout 用字符串文字衰减到a const char 指针,比较似乎是假的。查看答案以了解转换的原因。 - vsoftco
@vsoftco:根据C ++标准,此类型的指针比较是未指定的行为。看到 这个 - Destructor


答案:


是的,编译器正在转换 cout 到了 void*。如果你使用 -S 切换到代码的反汇编,你会看到这样的事情:

    mov edi, OFFSET FLAT:std::cout+8
    call    std::basic_ios<char, std::char_traits<char> >::operator void*() const
    cmp rax, OFFSET FLAT:.LC0
    setb    al
    test    al, al

这说清楚了 operator void* 是罪魁祸首。

与Bill Lynch所说的相反,我能够用它重现它 —std=c++11 上 编译器资源管理器。但是,它似乎确实是一个实现缺陷,因为C ++ 11应该已经被替换 operator void* 同 operator bool 上 basic_ios


9
2018-04-18 22:11



在c ++ 11中,没有 operator void *() 上 std::ostream。这将是一个实现缺陷。 - Bill Lynch
我认为这是g ++ 4.9中的一个缺陷(g ++ 5拒绝它) - vsoftco
g ++ 4.9 不 在某些方面完全符合C ++ 11,不会破坏它的ABI。这是其中之一。 g ++ 5将完全符合C ++ 11标准。 - Raphael Addile
是的,我只是仔细检查了C ++ 11中的更改​​。 - zneak


这仅在C ++ 11之前有效。

你基本上是这样做的: ((void *) std::cout) < ((char *) "test")


5
2018-04-18 22:09



对不起,我把它拿回来,没用 -std=c++11.... g ++ 5确实拒绝它,g ++ 4.9.2没有,即使有 -std=c++11。 - vsoftco