字符串流在读取基元时是否会抛出异常?

时间:2012-07-07 21:09:19

标签: c++ stringstream

查看一些旧代码,我们有很多类似的东西:

// 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();
}

当stringstream读取一个原语时,它是否会抛出异常?读字符串怎么样?

2 个答案:

答案 0 :(得分:10)

总结几个答案

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

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

根据 Apache C++ Standard Library User's Guide

  

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

     

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

     

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

     

通常,您应该记住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 "";
    }
}

这样做有点过分了,因为根据Handling bad_alloc,如果创建流失败,则需要担心更大的问题,程序可能会退出。因此,假设它已经过去创建流,那么badbit可能会被设置的可能性极小。 (Stream分配内存&lt; sizeof(int))。

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

string do_something(int in)
{
    stringstream out;
    out << std::fixed << in;
    return out.str();
}

答案 1 :(得分:2)

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

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