抛出引用类型的异常为何会调用拷贝构造函数?
抛出引用类型的异常为何会调用拷贝构造函数?
这其实是C++异常机制的一个核心规则——当你抛出一个对象(哪怕是以引用的形式抛出)时,编译器会自动创建该对象的副本作为异常对象,这个副本会被存储在专门的异常内存区域,用于后续的catch块捕获。而创建这个副本的过程,就必须调用类的拷贝构造函数。
看你给出的这段代码:
struct Error { Error() {} Error(const Error&) = delete; }; int main() { Error& error = *new Error; throw error; }
这里你明确删除了Error的拷贝构造函数,编译器在尝试创建异常对象副本时找不到可用的拷贝构造,自然就会报错:
error: declared here Error(const Error&) = delete;
而当你抛出指针类型时,情况就完全不同了:你实际抛出的是指针变量本身的值(也就是它指向的内存地址),这个值是一个简单的整数类型(在64位系统里就是8字节的数值),复制它不需要调用任何自定义的构造函数——既不需要拷贝指针指向的Error对象,也不需要Error类提供任何特殊成员函数。
比如这段代码:
int main() { Error* error = new Error; throw error; }
它能正常编译,因为本质上只是复制了一个内存地址数值,和Error类的拷贝构造函数没有任何关系。
补充个小细节:如果你的类提供了移动构造函数,编译器可能会优先调用移动构造来创建异常对象,但如果移动构造也不可用,就会 fallback 到拷贝构造——但不管是移动还是拷贝,都需要类提供对应的构造函数,否则就会像你第一个例子那样编译失败。
内容的提问来源于stack exchange,提问作者Andrey Rubliov
相关产品推荐
相关产品推荐

