C++ 抛出对象复制构造——为什么?
我希望能够抛出一个构造的对象,但在抛出之前对其进行修改 (使用)。 鉴于: 如您所见,捕获的异常对象不是最初抛出的对象。 如果我删除对C++ 抛出对象复制构造——为什么?,c++,exception-handling,C++,Exception Handling,我希望能够抛出一个构造的对象,但在抛出之前对其进行修改 (使用)。 鉴于: 如您所见,捕获的异常对象不是最初抛出的对象。 如果我删除对tweak()的调用,我会得到: my_exception(): this=1001000f0 &e=1001000f0 ~my_exception() 对于调用tweak()的情况,为什么要调用复制构造函数?我希望tweak()对最初构造的对象进行操作,而不复制。有没有办法防止复制构造 仅供参考:我使用的是g++4.2.1(MacOSX上Xcode的一
tweak()
的调用,我会得到:
my_exception(): this=1001000f0
&e=1001000f0
~my_exception()
对于调用tweak()
的情况,为什么要调用复制构造函数?我希望tweak()
对最初构造的对象进行操作,而不复制。有没有办法防止复制构造
仅供参考:我使用的是g++4.2.1(MacOSX上Xcode的一部分)。值引发异常。您不能将引用作为引用抛出。尝试时,会复制对象(使用静态已知类型) 顺便说一句,这就是为什么让异常可克隆是一个好主意的原因之一,并且使用虚拟的恢复方法 编辑(参见注释):例如,通过C回调传播异常是未定义的行为。但是,如果您已经定义了一个合适的异常类,那么您可以克隆它,并在C++中通过virtual方法重新启动调用链
干杯,值引发异常。您不能将引用作为引用抛出。尝试时,会复制对象(使用静态已知类型) 顺便说一句,这就是为什么让异常可克隆是一个好主意的原因之一,并且使用虚拟的恢复方法 编辑(参见注释):例如,通过C回调传播异常是未定义的行为。但是,如果您已经定义了一个合适的异常类,那么您可以克隆它,并在C++中通过virtual方法重新启动调用链
干杯&hth.,AFAIK在您的行中发生以下情况
抛出我的异常().tweak()代码>:
创建新的my_异常对象(本地,在堆栈上),tweak()返回对此本地对象的引用。然后,当抛出此引用时,您将超出范围,本地对象将被删除。因此,实现将类复制到动态内存以保持引用有效
在第二种情况下,您按值抛出它,并立即将其分配到动态内存中。AFAIK在您的行中发生以下情况抛出我的异常()代码>:
创建新的my_异常对象(本地,在堆栈上),tweak()返回对此本地对象的引用。然后,当抛出此引用时,您将超出范围,本地对象将被删除。因此,实现将类复制到动态内存以保持引用有效
在第二种情况下,您按值抛出它,并立即将其分配到动态内存中。为了补充Alf的答案,当您不调用tweak()
时,您不会得到复制操作,这是因为标准允许(但不要求)省略对复制构造函数的调用以创建临时异常对象。来自C++03 15.1/5(引发异常):
如果可以使用临时对象
在不改变环境的情况下被淘汰
除以下内容外,本计划的含义:
施工人员和承包商的执行
与使用
临时对象(12.2),然后
处理程序中的异常可以是
直接用参数初始化
扔的表情。当
抛出的对象是类对象,并且
复制构造函数用于
未初始化临时副本
如果可以访问,则程序的格式不正确
(即使临时对象可能
否则将被淘汰)
如果您将复制构造函数设置为私有,gcc将给您一个错误(即使当构造函数是公共的时,它也不会被调用)。MSVC不会给出错误,但我认为应该是这样。为了补充Alf的答案,当您不调用tweak()
时,您不会得到复制操作,这是因为标准允许(但不要求)省略对复制构造函数的调用来创建临时异常对象。来自C++03 15.1/5(引发异常):
如果可以使用临时对象
在不改变环境的情况下被淘汰
除以下内容外,本计划的含义:
施工人员和承包商的执行
与使用
临时对象(12.2),然后
处理程序中的异常可以是
直接用参数初始化
扔的表情。当
抛出的对象是类对象,并且
复制构造函数用于
未初始化临时副本
如果可以访问,则程序的格式不正确
(即使临时对象可能
否则将被淘汰)
如果您将复制构造函数设置为私有,gcc将给您一个错误(即使当构造函数是公共的时,它也不会被调用)。MSVC不会给出错误,但我认为应该是这样。那么您如何修改我的示例以使用clone()和/或虚拟恢复方法呢?@Paul:我不会。但是,在我写这篇文章时,你没有解释你的tweak
方法要实现什么。猜测一下,它意味着做一些额外的初始化,一个好的方法是定义一个派生类,并在throw
语句中使用该类。干杯&嗯,我不明白需要一个虚拟的再投掷者。如果您通过引用捕获并使用throw代码>,一旦实现隐藏了异常,就不会再进行复制。我倾向于对第一行进行向上投票,但同时倾向于对第二行进行向下投票。在很少的情况下,您实际上希望异常是可克隆的
和可重试的
。在一般情况下,通过抛出可以很容易地获得重新抛出
在异常处理程序中没有参数,并且克隆也没有用处。(这两种情况的唯一情况是,在没有C++的情况下,在一个线程中捕获并重新抛出另一个线程。
my_exception(): this=7fff5fbfeae0
my_exception( my_exception const& )
~my_exception()
&e=1001000f0
~my_exception()
my_exception(): this=1001000f0
&e=1001000f0
~my_exception()