c++中的字符串构建异常是what()

String building in C++ exception’s what()

本文关键字:what 异常 构建 字符串 c++      更新时间:2023-10-16

这个答案声明了一个private static ostringstream。这个线程安全吗?如果两个线程同时抛出(并捕获,并记录what())异常,这工作可靠吗?如果我在本地声明ostringstream,如:

virtual const char* what() const throw()
{
    std::ostringstream cnvt.str( "" );
    cnvt << runtime_error::what() << ": " << getNumerator()
         << " / " << getDenominator();
    return cnvt.str().c_str();
}

是否有缺点(内存泄漏,或非法指针)?或者这是线程安全的方式吗?

No。它一点也不安全(而且对我来说效率很低,可以单独用std::string来做)。为了安全起见,将ostringstream声明为thread_local

static thread_local ostringstream cnvt;

还应该使cnvt将字符串输出到某个成员字符串,以便不返回悬空指针。

class DivideByZeroException: public runtime_error {
public:
  DivideByZeroException(int x, int y)
    : runtime_error( "division by zero" ), numerator( x ), denominator( y )
    {}
  virtual const char* what() const throw()
  {
    cnvt.str( "" );
    cnvt << runtime_error::what() << ": " << getNumerator()
         << " / " << getDenominator();
    error = cnvt.str();
    return error.c_str();
  } 
   /*...*/
   private:
     std::string error;
     int numerator;
     int denominator;
   static thread_local ostringstream cnvt;
};

还有,如果例外是"除以0",你不觉得存储分母有点傻吗?它总是0 !否则你不会抛出"除零"错误!

,最后由与数学误差有关的std::domain_error推导出0除法误差更合适。

what()是错误的地方建立字符串IMHO(尽管有不同的观点)。

std::runtime_error已经包含了一个字符串,所以我们使用这个字符串。

#include <stdexcept>
#include <string>
struct DivideByZero : std::runtime_error
{
    DivideByZero(int x, int y)
    : std::runtime_error( make_message(x,y) )
    {}
private:
    static std::string make_message(int x, int y)
    {
        return std::string("division by zero: " + std::to_string(x) + '/' + std::to_string(y));
    }
};