为什么在初始化构造函数列表参数时会发生异常?

时间:2017-03-17 03:23:29

标签: c++ c++11

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第5版779页说

  

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

我很困惑,无法想到发生这种情况的时候,任何人都可以给我 一个例子?

4 个答案:

答案 0 :(得分:2)

以下是一个例子:

struct S
{
    S(char *);
};

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

new char[0x7FFFFFFF]可能会抛出内存异常。

答案 1 :(得分:0)

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

答案 2 :(得分:0)

当构造函数调用中抛出异常时会发生这样的事情;隐式或显式。

例如:

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 )语法上不可能在以后初始化。所以答案是完全中止构造函数调用。

答案 3 :(得分:-1)

示例:抛出异常:读取访问冲突。

#include <iostream>

using namespace std;

class X
{
     int a;
     int b;
     int* c;

   public:
       X(int a, int b, int* c = nullptr) try : a(a), b(b=c[0]) 
       {
       }
       catch (...)
       {
           cout << "Exception occured";
       }
};

int main()
{
    X v(1,0);

    return 0;
}
  

消息:c为nullptr。