【问题标题】:Can objects with private copy constructors be thrown?可以抛出具有私有复制构造函数的对象吗?
【发布时间】:2012-04-23 14:56:37
【问题描述】:

我遇到了一些我不清楚的异常问题。在 C++ 中,当一个对象被抛出时,它首先被复制到一个临时对象,然后这个临时对象被传递给捕获代码。复制涉及使用对象的类复制构造函数。 AFAIK,这意味着如果一个类具有私有复制构造函数,则不能将其用作异常。但是在VS2010中,编译运行如下代码:

class Except
{
    Except(const Except& other) { i = 2; }
public:
    int i;
    Except() : i(1) {}
};

int main()
{
    try
    {
        Except ex1;
        throw ex1;          // private copy constructor is invoked
    }
    catch (Except& ex2)
    {
        assert(ex2.i == 2); // assert doesn't yell - ex2.i is indeed 2
    }
    return 0;
}

这合法吗?

【问题讨论】:

  • 尝试添加打印或调试并查看调用顺序,也许事情并没有像你想象的那样执行。
  • 我在 VS2010 上得到了相同的行为,但它在 gcc v4.3.4 上失败了here。
  • 可能是临时对象是构造的,而副本被优化掉了。类似于返回值优化。
  • @DumbCoder,它使用 VS2010 为我编译和执行。
  • @selalerer - 调试显示私有副本 c'tor 确实在预期时间输入。 @zabulus - 正如人们所期望的那样,它无法编译,但错误出现在 catch 行。我的问题是throw。

标签: c++ visual-studio-2010 exception private copy-constructor


【解决方案1】:

不,不是。

15.1.5 当抛出的对象是类对象时,复制/移动构造函数和析构函数应该是可访问的, 即使省略了复制/移动操作

【讨论】:

    【解决方案2】:

    这是不合法的。标准 15.1/5

    如果使用临时对象可以不用改变就可以消除 程序的意义除了构造函数的执行 和与使用临时对象相关的析构函数 (12.2),那么可以直接初始化handler中的异常 使用 throw 表达式的参数。 当抛出的物体是 类对象,以及用于初始化的复制构造函数 临时副本不可访问,程序格式错误(即使 否则可以消除临时对象)。同样,如果 该对象的析构函数不可访问,程序是 格式错误(即使临时对象可能是 淘汰)。

    【讨论】:

    • 哇,这太神奇了,从来没有想过它会发生。谢谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-03
    • 2013-06-05
    相关资源
    最近更新 更多