为什么写空 std::istringstream.rdbuf() 会设置 failbit?

Why does writing empty std::istringstream.rdbuf() set failbit?

我了解到,我可以通过输出 istream 的 rdbuf() 将 C++ std::istream 复制到 C++ std::ostream。我用了好几次,效果很好。

今天我遇到了麻烦,因为这个操作设置了 badbit,如果 std::istream 是空的(至少对于 std::istringstream)。我编写了以下代码来演示我的问题:

#include <stdio.h>
#include <sstream>

int main(int argc, char *argv[])
{
    std::ostringstream ss;

    ss << std::istringstream(" ").rdbuf(); // this does not set failbit
    printf("fail=%d\n", ss.fail());

    ss << std::istringstream("").rdbuf(); // why does this set failbit ???
    printf("fail=%d\n", ss.fail());
}

我尝试了 Windows/VS2017 和 Linux/gcc-9.20,两者的行为相同。

我在默认值为 std::istringstream("") 的方法签名中使用 std::istream&。调用代码应该能够传递一个可选的 istream,它附加到一些其他数据。

我知道,我可以编写两种方法,一种带有额外的 std::istream& 参数,但我想避免重复代码。

提前致谢,

马里奥

20 年 4 月 22 日更新

我现在使用以下代码:

#include <stdio.h>
#include <sstream>

int main(int argc, char *argv[])
{
    std::ostringstream out;
    std::istringstream in("");
    while (in)
    {
        char Buffer[4096];
        in.read(Buffer, sizeof(Buffer));
        out.write(Buffer, in.gcount());
    }
    printf("fail=%d\n", out.fail());
}

我还添加了有关在将空文件复制到

时设置 failbit 的警告

ostream::operator<< 的文档描述了读取流的以下行为:

Behaves as an UnformattedOutputFunction. After constructing and checking the sentry object, checks if sb is a null pointer. If it is, executes setstate(badbit) and exits. Otherwise, extracts characters from the input sequence controlled by sb and inserts them into *this until one of the following conditions are met:

   * end-of-file occurs on the input sequence;
   * inserting in the output sequence fails (in which case the character to be inserted is not extracted);
   * an exception occurs (in which case the exception is caught). 

If no characters were inserted, executes setstate(failbit). If an exception was thrown while extracting, sets failbit and, if failbit is set in exceptions(), rethrows the exception.

如您所知,这明确表示尝试插入空缓冲区将设置 failbit。如果你想让它成为“可选”,只需在插入缓冲区之前检查流是否良好,然后执行 ss.clear() 以清除故障位。