将std::cin直接重定向到std::cout

3

一个关于标准输入输出的练习要求我:

从标准输入读取输入并将其写入标准输出。

一个可能的解决方案是:

#include<iostream>
#include<string>

using std::cin; using std::cout;
using std::string;

int main()
{
    string word;
    while (cin >> word)
        cout << word;

    return 0;
}

在这个例子中,该字符串作为缓冲区。如果尝试通过执行以下操作来摆脱缓冲区:

#include<iostream>
using std::cin; using std::cout;

int main()
{
    while (cout << cin)
        ;
    return 0;
}

结果非常不同。当我运行此代码时,终端会输出一长串类似于“0x600d30”的字符流。
为什么会这样?这些程序为什么表现不同?

1
你是如何让 cout << cin 编译通过的? - emlai
1
我看不到这个编译 - scohe001
@scohe001 https://ideone.com/zRMP7G 编译完美。 - Andrey
我在Linux Mint Debian Edition上使用g++ 4.8.2。我没有使用任何标志,只是运行了(g++ example.cpp -o example)。 - Jose_mr
@Andrey 你做了什么不同的事情? - scohe001
1
@scohe001,我选择了“C++”,而你选择了“C++14”。不知道在这种特定情况下有什么区别。 - Andrey
2个回答

6

cout << cin不能按你想象的方式工作。在C++11及更高版本中,它甚至无法编译。

你看到的是(现在已过时的)"safe bool"习惯用法的不幸副作用。

在C++11之前,std::istream可以隐式转换为void*以模拟bool语义。(自C++11以来,explicit operator bool() const填补了这个角色)

因此,代码如下:

while (cout << cin)

可以编译成C++98或C++03,因为它可以隐式转换为:

while (cout << static_cast<void*>(cin) )

cin没有错误状态时,此转换允许生成任何非空的void*。在您的情况下,它正在生成指针0x600d30

+1,但是如果你能告诉如何实现OP想要的行为,我会给你+2(如果我可以投两票)。 - Enlico
1
@EnricoMariaDeAngelis 我倾向于同意,但在这种情况下,OP已经在问题中展示了所需的行为,只是想知道为什么“cout<<cin”会做出它所做的事情。 - Drew Dormann

1
在第一种解决方案中,您从 cin 中提取一个字符串并重新注入到 cout 中。但在第二种方式中,编译器尝试将 cin 转换为适合注入到 cout 中的值。
您的实现将 cin 转换为指针并重复打印它。我的实现仅将 cin 转换为布尔值并重复打印 1
但要注意,即使是您的第一个版本也不能完全透明地处理多个空格或制表符,并且可能也无法保留行。我更喜欢以下方式:
#include<iostream>
#include <string>


int main()
{
    std::string line;

    while (std::getline(std::cin, line)) {
        std::cout << line << std::endl;
    }
    return 0;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接