例如,我正在编写一个多线程时间关键型应用程序,可以实时处理和传输音频。音频中断是完全不可接受的。这是否意味着我不能使用STL,因为抛出异常时可能会减慢速度?
答案 0 :(得分:28)
通常,如果new失败,STL容器自己抛出的唯一异常是std :: bad_alloc。唯一的其他时间是用户代码(例如构造函数,赋值,复制构造函数)抛出的时间。如果你的用户代码永远不会抛出,那么你只需要防止新的投掷,你最不可能做到这一点。
其他可能引发异常的事情: - at()函数可以抛出std :: out_of_range,如果你超出范围访问它们。无论如何,这是一个严重的程序错误。
其次,异常并不总是很慢。如果您的音频处理中发生异常,可能是因为您需要处理的严重错误。错误处理代码可能比异常处理代码要昂贵得多,以便将异常传输到catch站点。
答案 1 :(得分:8)
如果一个STL容器抛出,你可能遇到的问题比减速要大得多:)
答案 2 :(得分:7)
在前面的答案中没有明确写出来,所以:
使用STL不会删除释放您分配的对象资源的RAII代码。
例如:
void doSomething()
{
MyString str ;
doSomethingElse() ;
}
在上面的代码中,编译器将生成释放MyString资源的代码(即调用MyString析构函数),无论同时发生什么,包括doSomethingElse是否抛出异常,或者是否执行“返回“在函数范围结束之前。
如果您遇到问题,那么您应该修改自己的思维模式,或尝试使用C.
通常,当发生异常(and only when)时,您的性能会受到影响。
但是,只有在以下情况下才会发送异常:
这里的关键字是“例外”,这很好,因为我们正在讨论“异常”(参见模式?)。
在你的情况下,如果你抛出一个异常,很可能会发生很糟糕的事情,你的程序无论如何都会崩溃。
在这种情况下,您的问题不是处理性能问题。它是处理错误的优雅处理,或者更糟糕的是,优雅地终止程序(包括“对不起”消息框,将未保存的数据保存到临时文件中以便以后恢复等)。
这意味着(除非在特殊情况下),不要将异常用作“返回数据”。当发生非常糟糕的事情时抛出异常。只有在知道如何处理异常时才捕获异常。避免尝试/捕捉(除非你知道如何处理异常)。
现在我们知道了:
我们应该讨论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)
你说话好像异常是不可避免的。只是不要做任何可能导致异常的事情 - 修复你的错误,验证你的输入。