11

我遇到了一些我不清楚的异常问题。在 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;
}

这合法吗?

4

2 回答 2

13

这不合法。标准 15.1/5

如果除了执行与使用临时对象相关的构造函数和析构函数(12.2)之外,可以在不改变程序含义的情况下消除临时对象的使用,则可以直接使用参数初始化处理程序中的异常的 throw 表达式。当抛出的对象是一个类对象,并且用于初始化临时副本的复制构造函数不可访问时,程序是非良构的(即使临时对象可以被消除)。类似地,如果该对象的析构函数不可访问,则程序格式错误(即使临时对象可以被消除)。

于 2012-04-11T10:05:29.023 回答
2

不,这不对。

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

于 2012-04-11T10:06:07.160 回答