【问题标题】:Why can an exception occur when initializing the constructor list parameter?为什么初始化构造函数列表参数时会出现异常?
【发布时间】:2017-03-17 03:23:28
【问题描述】:
template <typename T>
Blob<T>::Blob(std::initializer_list<T> il) try :
data(std::make_shared<std::vector<T>>(il)) {
/* empty body */
} catch(const std::bad_alloc &e) { handle_out_of_memory(e); }

C++ Primer第五版779页说

注意关键字 try 出现在构造函数开头的冒号之前 初始化器列表和形成(在这种情况下为空)构造函数的大括号之前 功能体。与此 try 关联的 catch 可用于处理异常 从成员初始化列表中或从构造函数中抛出 身体。 值得注意的是,在初始化构造函数时可能会发生异常 参数。此类异常不是函数 try 块的一部分。函数试试 块仅处理构造函数开始执行后发生的异常。作为 对于任何其他函数调用,如果在参数初始化期间发生异常,则 异常是调用表达式的一部分,并在调用者的上下文中处理。

我很困惑,想不出什么情况/什么时候发生,谁能给我 一个例子?

【问题讨论】:

  • 像这样脱离上下文,很难知道“初始化构造函数的参数”是什么意思。 any 函数调用的参数必须进行评估,这可能会导致异常,特别是如果这些参数是从函数调用派生的。
  • @MarkRansom 我已经添加了更多信息,现在我想你可以知道它们的意思了。
  • 您应该更改标题,您似乎是在通过成员初始化器列表询问成员的初始化,而不是关于参数初始化。类成员不是参数
  • @M.M 我的说法和书上差不多,删掉'list'这个词?我想不出更准确的表达方式。
  • @K.Robert 要点是,当您显然不是在谈论参数时,您使用的是“参数”一词。

标签: c++ c++11


【解决方案1】:

这是一个例子:

struct S
{
    S(char *);
};

int main()
{
    S s(new char[0x7FFFFFFF]);
}

new char[0x7FFFFFFF] 可能会引发内存不足异常。

【讨论】:

  • 这段代码无法编译:错误C2148:数组的总大小在VS2015中不得超过0x7fffffff字节,在VS2010中测试也是如此。
  • 错误:'new' 中的数组大小在 VS2010 中也必须为非负数。
  • @H.DJEMAI 添加一个空函数体
【解决方案2】:

如果在初始化参数时内存不足。

【讨论】:

    【解决方案3】:

    当在构造函数调用中抛出异常时,可能会发生这种情况;无论是隐式的还是显式的。

    例如:

    class spam {
      public:
         spam(int eggs) {
            throw std::exception();
         }
    };
    
    class foo {
      public:
        spam unused;
        const int q;
        foo() try : unused(1), q(123) {
    
        } catch(std::exception& e) { 
          std::cout << "spamspamspam\n";
        }
    };
    
    int main() {
       try {
          foo f; // exception thrown
       } catch (std::exception& e) {
          std::cout << "It didn't stop there!\n";
       }
    
       return 0;
    }
    

    在终端上打印“spamspamspam\n 它并没有停在那里!\n”,然后退出并中止。请注意,可以捕获异常,但之后会继续传播。

    这是因为在 thrower 之后要初始化的任何成员实际上都没有初始化,并且是 const 成员或引用(例如我的示例中的 const int q)在语法上不可能在以后初始化。所以答案是完全中止构造函数调用。

    【讨论】:

    • 谢谢,您帮助理解为什么会发生第二个异常。在初始化构造函数的参数时,第一个和第二个异常都不会发生,尽管一个函数 try 块不能解决问题。很有帮助,希望你不要删答案。
    猜你喜欢
    • 2013-07-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-02
    • 1970-01-01
    • 2022-01-19
    • 2010-10-16
    • 2010-09-14
    相关资源
    最近更新 更多