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

Why can an exception occur when initializing the constructor list parameter?

本文关键字:异常 初始化 构造函数 列表 参数 为什么      更新时间:2023-10-16
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++ 入门第五版 779 页说

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

我很困惑,想不出它发生的情况,任何人都可以给我 一个例子?

下面是一个示例:

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

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

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

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

例如:

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 << "spamspamspamn";
}
};
int main() {
try {
foo f; // exception thrown
} catch (std::exception& e) {
std::cout << "It didn't stop there!n";
}
return 0;
}

在终端上打印"spamspam 它没有止步于此!",然后以中止方式退出。 请注意,可以捕获异常,但之后会继续传播。

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