C++ c++;异常处理按引用传递:抛出的地址与捕获的地址不同?
问题:您是否看到addr1和addr2是不同的,知道为什么吗?当抛出异常时,会生成一个副本。您正在查看该副本的地址C++ c++;异常处理按引用传递:抛出的地址与捕获的地址不同?,c++,C++,问题:您是否看到addr1和addr2是不同的,知道为什么吗?当抛出异常时,会生成一个副本。您正在查看该副本的地址 (处理程序的异常怎么可能有相同的地址?当您抛出时,您退出了包含异常的块,因此它不再存在。您无法访问不存在的内容。)这很有意义。异常在抛出时被复制,这样它就可以在退出其源的堆栈帧后继续存在。一旦该异常退出它起源的{}块,该堆栈帧将弹出,其中的所有局部变量都将消失。因此必须进行复制。仅在通过值的情况下进行复制,对吗,但是在这里我粘贴了使用pass-by-reference的代码。thr
(处理程序的异常怎么可能有相同的地址?当您抛出时,您退出了包含异常的块,因此它不再存在。您无法访问不存在的内容。)这很有意义。异常在抛出时被复制,这样它就可以在退出其源的堆栈帧后继续存在。一旦该异常退出它起源的
{}
块,该堆栈帧将弹出,其中的所有局部变量都将消失。因此必须进行复制。仅在通过值的情况下进行复制,对吗,但是在这里我粘贴了使用pass-by-reference的代码。throw
是创建副本的原因。您正在捕获一个引用,但它是对由throw
@SamJ创建的副本的引用:您没有抓住要点。有两个不同的对象,本地对象myex
,它位于函数堆栈中,抛出对象(抛出表达式从堆栈复制到编译器定义的位置)。然后,如果您通过值捕获异常,则会执行从抛出对象到捕获异常的函数堆栈的第二次复制。请注意,必须保留原始异常,以防抛出代码>,它不能是myex
,因为堆栈(可能)被解开了。@SamJ:这不是一个问题,这是一个语句,它与这种情况无关,因为你没有调用函数。@SamJ:很抱歉让我的答案无人参与,但其他人已经用我的话回答了你的问题。不,我不依赖任何输出来确定答案,这只是它的工作方式。你说扔x代码>,编译器复制x
,然后找到它应该跳转到的位置进行捕获。我理解这一点,但我的问题与你的答案完全不同。在上面的程序中,您可以看到正在调用复制构造函数(如果您编写了一个复制构造函数,那么您就可以看到它),这将生成一个单独的obj副本。但实际上复制构造函数仅对临时对象(如按值传递)调用。@SamJ:但实际上复制构造函数仅对临时对象(如按值传递)调用。这是一个很好的陈述,也是一个错误。可以为临时对象以外的其他对象创建副本,在某些情况下,临时对象既不是副本的结果,也不会复制自身。
#include <iostream>
#include <exception>
using namespace std;
class myexception: public exception
{
virtual const char* what() const throw()
{
return "My exception happened";
}
};
int main ()
{
try
{
myexception myex;
printf("addr1:%x\n",&myex);
throw myex;
}
catch (exception& e)
{
printf("addr2:%x\n",&e);
cout << e.what() << endl;
}
return 0;
}
addr1:6d78c020
addr2:20a1080
My exception happened