【问题标题】:Why does exception::what not return a std::string [duplicate]为什么 exception::what 不返回 std::string [重复]
【发布时间】:2020-09-08 14:22:03
【问题描述】:

我试图提出自定义 std::exception 类,但我对如何正确实现 what() 感到困惑。

例如,让我们有

class int_error : std::exception
{
    int param;
public:
    int_error(int param)
        : param(param)
    {
    }

    char const* what() const override
    {
        // return "Error occurred while processing number " + param
        // How to return this?
    }
};

我不能使用std::string("text").c_str()(在函数返回之前被销毁)和任何与手动管理生命周期相关的东西(比如new char[])都不起作用(会泄漏内存),因为我永远不能删除它(因为我什至不能将指针存储在任何地方,因为whatconst)。

我知道我可以提前准备错误字符串(构造函数),然后在what 中返回它。

如果what 改为返回std::string,我就不会遇到这个困难。这是对 STL 的疏忽还是我遗漏了什么(我可能是)。

【问题讨论】:

  • 因为构造和复制std::string 也会抛出异常。在堆栈展开期间复制异常时抛出第二个异常会导致各种问题。

标签: c++ exception


【解决方案1】:

为什么 exception::what 不返回 std::string

因为有时需要在无法进行动态分配的情况下使用异常。例如,考虑处理异常std::bad_allocstd::string 可能需要动态分配,因此 std::exception 的 API 无法使用。

我知道我可以提前准备错误字符串(构造函数),然后直接返回。

这确实是你应该做的。但是请注意,存储 std::string 成员也有问题,因为它可能会抛出异常类的复制构造函数。

解决方案是继承自std::runtime_error。它有一个接受字符串的构造函数。它负责存储字符串的困难部分,而不会发生潜在的抛出。

【讨论】:

    【解决方案2】:

    KISS:将其设为类缓冲区:

    class int_error : std::exception
    {
        int param;
        char mutable buffer[64];
    public:
        int_error(int param)
            : param(param)
        {
        }
    
        char const* what() const override
        {
            // set buffer to "Error occurred while processing number " + param
            return buffer;
        }
    };
    

    【讨论】:

      【解决方案3】:

      您可以使用std::runtime_error。它基本上是std::exception,带有一个构造函数,该构造函数接受从what 返回的字符串。 std::runtime_error 上的 cppreference 页面也有一些很好的提示,为什么您不想使用 std::string 发送消息:

      注意事项

      因为复制 std::runtime_error 不允许抛出异常,所以该消息通常在内部存储为单独分配的引用计数字符串。这也是为什么没有构造函数采用 std::string&& 的原因:无论如何它都必须复制内容。

      “...不允许抛出异常”对于std::exception 也是如此。您不希望在原始异常仍在飞行时引发另一个异常。

      【讨论】:

        猜你喜欢
        • 2015-04-17
        • 2020-10-25
        • 1970-01-01
        • 1970-01-01
        • 2018-07-22
        • 2018-10-06
        • 2021-07-10
        • 1970-01-01
        • 2015-08-04
        相关资源
        最近更新 更多