叮当是正确的。(感谢@NathanOliver 的评论。)
[except.throw]/3
抛出异常复制初始化 ([dcl.init], [class.copy.ctor]) 一个临时对象,称为异常对象。表示临时值的左值用于初始化匹配处理程序中声明的变量([except.handle])。
[except.throw]/5
当抛出的对象是类对象时,为复制初始化选择的构造函数以及为复制初始化选择的构造函数将抛出的对象视为左值,即使复制/移动操作也应不可删除且可访问被省略([class.copy.elision])。
异常对象被认为是一个左值,在catch子句的参数的复制初始化中,选择了复制构造函数。复制操作可能会被忽略为优化;但是复制构造函数仍然必须存在并且可以访问。
我已将此报告为gcc bug 103048。
顺便说一句,由于强制复制省略(自 C++17 起) ,导致的异常对象的复制初始化throw B{};
很好。
在对象的初始化中,当初始化表达式是与变量类型相同的类类型(忽略 cv-qualification)的纯右值时:
T x = T(T(f())); // only one call to default constructor of T, to initialize x
首先,如果 T 是一个类类型并且初始化器是一个纯右值表达式,其 cv 非限定类型与 T 相同,则初始化器表达式本身,而不是从它的临时物化,用于初始化目标对象:见复制省略(C++17 起)