代码之家  ›  专栏  ›  技术社区  ›  Konvt

标准库中异常构造函数参数类型问题

  •  2
  • Konvt  · 技术社区  · 7 月前

    在标准库中,异常类构造函数的参数类型,例如 std::runtime_error ,遵循以下模式:

    runtime_error( const std::string& what_arg ); // (1)
    runtime_error( const char* what_arg );        // (2)
    runtime_error( const runtime_error& other );  // (3)
    

    让我困惑的是(1)使用 const std::string& 而不是 std::string ,这显然会导致构造函数内部的额外复制操作。

    如果参数类型为 std::string ,它不仅可以避免额外的复制操作,而且还可以 noexcept ;这是我最近意识到的结论:

    如果功能标记为 没有例外 有一个参数的类型可能会在构造过程中引发异常,那么即使保证会引发异常,也不会导致程序因异常而终止。

    这一点已得到证实 the test program .

    那么,为什么标准库异常构造函数参数列表不使用 std::string 或者,我的理解和结论以及测试程序是否不正确,甚至是一种未定义的行为?

    1 回复  |  直到 7 月前
        1
  •  3
  •   Alan Birtles    7 月前

    让我困惑的是(1)使用了const std::string&而不是std::string,这显然会导致构造函数内部的额外复制操作。

    我想你是在假设 std::runtime_error 用a实现 std::string 要存储的成员变量 what() 例如,情况不一定如此 libstdc++ has a special __cow_string member type , libc++ uses a special std::__libcpp_refstring member type ,MSVC使用 __std_exception_data 类型。

    超负荷服用 std::string 按值实际上会为没有 std::string 成员(一份副本给临时 std::string 第二种是内部格式)。r值引用过载至少不会比 const 参考,但我想没有人觉得这值得标准化工作,因为r值是在c++11中添加的(可能是因为没有实现实际使用 std::string 成员)。

    例外情况通常不会使用 std::string 为了避免您提到的问题,在创建异常时分配可能会失败(特别是如果异常是由于内存耗尽引起的),因此通常会使用一些专门的分配器,即使没有通用堆空间也不会失败。