为什么 Quantlib::Error class 在堆上分配一个 std::string ?

Why does the Quantlib::Error class allocate a std::string on the heap?

在最近的一次代码审查中,我对一些我认为很糟糕的事情说了一些不太客气的话。原来明显是受到了QuantLib::Errorclass的启发,长这样:

//! Base error class
class Error : public std::exception {
  public:
    /*! The explicit use of this constructor is not advised.
        Use the QL_FAIL macro instead.
    */
    Error(const std::string& file,
          long line,
          const std::string& functionName,
          const std::string& message = "");
    #ifdef QL_PATCH_MSVC_2013
    /*! the automatically generated destructor would
        not have the throw specifier.
    */
    ~Error() throw() override {}
    #endif
    //! returns the error message.
    const char* what() const QL_NOEXCEPT override;

  private:
    ext::shared_ptr<std::string> message_;
};

为什么成员变量是ext::shared_ptr<std::string>而不是普通的std::string?堆分配字符串对象本身的原因是什么? (QuantLib 代码库似乎几乎总是在任何地方堆分配所有内容,并引入 shared_ptr 来应对这种情况 - classic 反模式 - 但在这里做还有“只是为了保持一致性”让我觉得有点过分。我错过了什么吗?)

这是遵循标准库异常类型的行为。

它们应该可以在不抛出异常的情况下进行复制,因为在构造异常处理程序参数期间抛出异常会导致调用 std::terminate(并且可能在某些其他情况下需要异常的副本作为嗯)。

如果直接使用 std::string,复制异常可能会导致例如 std::bad_alloc 被抛出。使用 reference-counted 指针可以避免这种情况。