【问题标题】:How it is right way to throw object as a reference in C++?在 C++ 中将对象作为引用抛出的正确方法是什么?
【发布时间】:2014-08-05 16:25:01
【问题描述】:

我不明白,下面的代码是对的,

class cls
{
    //just to create obj
};

int main(int argc, char* argv[])
{
    try
    {
        throw cls();//throwing obj as ref
    }
    catch(cls &ref)
    {
    }

    return 0;
}

我将cls 对象作为参考抛出,它不会因为超出{ } 范围而死吗?

因为catch块不能访问try的变量。

【问题讨论】:

  • 接受的答案中的相关位是“异常对象的范围超出了发生抛出的块的范围。把它想象成生活在一个特殊的异常区域中本地对象所在的正常调用堆栈。”
  • 实例在任何适当的catch() 块中处理后将超出范围。
  • 你不是在抛出一个引用,你是在抛出一个对象。您只是在处理程序中获得对它的引用。

标签: c++ exception-handling pass-by-reference


【解决方案1】:

当你抛出一个异常时,你实际上会生成一个异常对象的副本。它是catch 块接收的副本,因此即使原始对象超出范围,它也不会超出范围。

【讨论】:

  • 即使 ctor/dtor 有副作用,也可以省略该副本。
  • @Deduplicator 如果省略了副本,则意味着从未构造过临时对象,因此临时对象的范围变得无关紧要。最终结果是一样的,throw 范围之外的对象被传递给catch 块。
【解决方案2】:

throw 将复制初始化对象,这就是它能够捕获引用的方式。也就是说,随意扔可能不复杂的对象可能不如使用std::exception

【讨论】:

  • +1。这也是一个很好的答案。但另一个是第一个。
  • 副本可以作为 as-if 规则的例外被省略。
  • 仅在某些情况下,如果它被省略,这仅仅意味着它将被限定为 catch 块中的自动变量,否则无论如何都会被复制。
【解决方案3】:

异常处理机制将获取 throw 表达式的值并将其复制到它为此目的保留的内存区域中。因此抛出异常总是“按值”,不能“按引用”。

当激活异常处理程序时,catch 参数将使用异常处理机制创建的副本进行初始化:如果参数是引用类型,则初始化为引用该副本,如果参数不是引用类型,则它是通过复制构造初始化的。

【讨论】:

    猜你喜欢
    • 2021-07-30
    • 1970-01-01
    • 2011-12-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-03
    • 1970-01-01
    相关资源
    最近更新 更多