10

查看一些旧代码,我们有很多类似以下的内容:

// This is dumb
string do_something(int in)
{
    stringstream out;
    try
    {
        out << std::fixed << in;
    }
    catch(std::exception &e)
    {
        out << e.what();
    }

    return out.str();
}

// Can't we just do this? Can this ever fail?
string do_something_better(int in)
{
    stringstream out;
    out << std::fixed << in;
    return out.str();
}

当一个字符串流读取一个原语时,它会抛出异常吗?读取字符串时怎么办?

4

2 回答 2

11

总结几个答案

默认情况下,流不会抛出异常。如果启用,它们可以。

stringstream out;
out.exceptions(std::ios::failbit);   // throw exception if failbit gets set

根据 Apache C++ 标准库用户指南

标志 std::ios_base::badbit 指示底层流缓冲区存在问题。这些问题可能是:

内存不足。没有可用于创建缓冲区的内存,或者由于其他原因(例如从流外部提供),缓冲区的大小为 0,或者流无法为其自己的内部数据分配内存,如 std::ios_base:: iword() 和 std::ios_base::pword()。

底层流缓冲区引发异常。流缓冲区可能会失去其完整性,例如内存不足、代码转换失败或来自外部设备的不可恢复的读取错误。流缓冲区可以通过抛出异常来指示完整性丢失,该异常被流捕获并导致在流的状态中设置坏位。

通常,您应该记住,badbit 表示可能无法恢复的错误情况,而 failbit 表示可能允许您重试失败操作的情况。

所以看起来最安全的方法是

string do_something(int in)
{
    stringstream out; // This could throw a bad_alloc
    out << std::fixed << in; // This could set bad or fail bits

    if(out.good())
    {
        return out.str();
    }
    else
    {
        return "";
    }
}

这有点过头了,因为根据处理 bad_alloc如果创建流失败,需要担心更大的问题,并且程序可能会退出。因此,假设它通过创建流,它是可能的,但极不可能设置坏位。(流被分配内存< sizeof(int))。

也不太可能设置故障位(不确定读取堆栈的用例,而不是损坏的堆栈)。所以下面的代码就足够了,因为此时从流错误中恢复是不可能的。

string do_something(int in)
{
    stringstream out;
    out << std::fixed << in;
    return out.str();
}
于 2012-07-09T17:36:27.610 回答
2

所有流,包括,都可以在读取istringstreams时抛出异常(用 控制),例如。ios::exceptions当他们用完输入时。另外,它们可能会在内存不足时抛出(例如,在构造当前读取的字符串时)。

但是,您的代码示例执行写入(?)AFAIK 写入并且int不应该产生任何异常,除了明显的内存不足错误(您的代码不能很好地处理)。

于 2012-07-07T21:19:01.623 回答