如果在抛出异常时我无法承受缓慢的性能,我可以使用STL吗?

时间:2008-10-02 20:16:20

标签: c++ performance exception

例如,我正在编写一个多线程时间关键型应用程序,可以实时处理和传输音频。音频中断是完全不可接受的。这是否意味着我不能使用STL,因为抛出异常时可能会减慢速度?

7 个答案:

答案 0 :(得分:28)

通常,如果new失败,STL容器自己抛出的唯一异常是std :: bad_alloc。唯一的其他时间是用户代码(例如构造函数,赋值,复制构造函数)抛出的时间。如果你的用户代码永远不会抛出,那么你只需要防止新的投掷,你最不可能做到这一点。

其他可能引发异常的事情: - at()函数可以抛出std :: out_of_range,如果你超出范围访问它们。无论如何,这是一个严重的程序错误。

其次,异常并不总是很慢。如果您的音频处理中发生异常,可能是因为您需要处理的严重错误。错误处理代码可能比异常处理代码要昂贵得多,以便将异常传输到catch站点。

答案 1 :(得分:8)

如果一个STL容器抛出,你可能遇到的问题比减速要大得多:)

答案 2 :(得分:7)

在前面的答案中没有明确写出来,所以:

C ++中出现异常

使用STL不会删除释放您分配的对象资源的RAII代码。

例如:

void doSomething()
{
    MyString str ;
    doSomethingElse() ;
}

在上面的代码中,编译器将生成释放MyString资源的代码(即调用MyString析构函数),无论同时发生什么,包括doSomethingElse是否抛出异常,或者是否执行“返回“在函数范围结束之前。

如果您遇到问题,那么您应该修改自己的思维模式,或尝试使用C.

异常应该是例外

通常,当发生异常(and only when)时,您的性能会受到影响。

但是,只有在以下情况下才会发送异常:

  • 您有一个特殊事件要处理(即某种错误)
  • 在非常特殊的情况下(即来自堆栈中多个函数调用的“大量返回”,例如在执行复杂搜索时,或在线程优雅中断之前展开堆栈)

这里的关键字是“例外”,这很好,因为我们正在讨论“异常”(参见模式?)。

在你的情况下,如果你抛出一个异常,很可能会发生很糟糕的事情,你的程序无论如何都会崩溃。

在这种情况下,您的问题不是处理性能问题。它是处理错误的优雅处理,或者更糟糕的是,优雅地终止程序(包括“对不起”消息框,将未保存的数据保存到临时文件中以便以后恢复等)。

这意味着(除非在特殊情况下),不要将异常用作“返回数据”。当发生非常糟糕的事情时抛出异常。只有在知道如何处理异常时才捕获异常。避免尝试/捕捉(除非你知道如何处理异常)。

STL怎么样?

现在我们知道了:

  • 你仍然想使用C ++
  • 你的目标不是为了它的乐趣每一秒抛出一千个例外

我们应该讨论STL:

STL(如果可能的话)通常会验证你是否做错了。如果你这样做,它将抛出异常。尽管如此,在C ++中,你通常不会支付你不会使用的东西。

一个例子是访问矢量数据。

如果你知道你不会超出界限,那么你应该使用运算符[]。

如果你知道你将无法验证边界,那么你应该使用()的方法。

示例A:

typedef std::vector<std::string> Vector ;

void outputAllData(const Vector & aString)
{
   for(Vector::size_type i = 0, iMax = aString.size() ; i != iMax ; ++i)
    {
       std::cout << i << " : " << aString[i] << std::endl ;
    }
}

例B:

typedef std::vector<std::string> Vector ;

void outputSomeData(const Vector & aString, Vector::size_type iIndex)
{
   std::cout << iIndex << " : " << aString.at(iIndex) << std::endl ;
}

示例A“信任”程序员,并且在验证中没有时间丢失(因此,如果出现错误,则当时抛出异常的可能性更小 ...其中通常意味着错误/异常/崩溃通常会在之后发生,这将无助于调​​试并且会让更多数据被破坏。

示例B要求向量验证索引是否正确,如果没有则抛出异常。

选择权在你手中。

答案 3 :(得分:3)

不要害怕性能方面的例外情况。

在C ++的旧时代,在某些编译器上启用异常的构建可能会慢得多。

如果您的构建有或没有异常处理,那么这无关紧要。

一般情况下,除非内存不足,否则STL不会抛出异常,因此对于您的应用程序类型也不会有问题。

(现在不要使用GC的语言.....)

答案 4 :(得分:3)

值得注意几点:

  • 您的应用程序是多线程的。如果一个线程(可能是GUI一个)被异常减慢,它不应该影响实时线程的性能。

  • 例外情况适用于特殊情况。如果您的实时线程中出现异常,则可能意味着无论如何都无法继续播放音频。如果您发现无论出于何种原因不断处理这些线程中的异常,请重新设计以避免出现异常。

我建议您接受STL,除非STL本身证明太慢 - 但请记住:先测量,优化第二次,并采用自己的异常处理'您应用程序中的异常情况(音频硬件故障,无论如何)。

答案 5 :(得分:1)

我很难想到STL的哪些部分指定他们可以引发异常。根据我的经验,大多数错误处理由返回代码处理或作为STL使用的先决条件。 传递给STL的对象肯定会引发异常,例如复制构造函数,但无论使用STL,这都是一个问题。 其他人提到了诸如std::vector::at()之类的功能,但您可以执行检查或通常使用备用方法以确保不会抛出任何异常。

当然,STL的一个特定实现可以执行“检查”,通常用于调试构建,对你使用STL,我认为它只会引发一个断言,但也许有些会引发异常。

如果没有try / catch存在,我相信除非您自己的类引发异常,否则不会产生最小的性能损失。

在Visual Studio上,您可以完全禁用C ++异常,请参阅Project Properties -> C/C++ -> Code Generation -> Enable C++ Exceptions。我认为这在大多数C ++平台上都可用。

答案 6 :(得分:0)

你说话好像异常是不可避免的。只是不要做任何可能导致异常的事情 - 修复你的错误,验证你的输入。