3

C++ 标准,第 15.1.4 段说:

被抛出异常的临时副本的内存以未指定的方式分配,除非在 3.7.3.1 中注明。只要有针对该异常执行的处理程序,临时性就会持续存在。

我想知道为什么这段代码会崩溃(我知道这不是最佳做法):

class magicException
{
private:
    char* m_message;

public:
    magicException(const char* message)
    {
        m_message = new char[strlen(message) + 1];
        strcpy(m_message, message);
    }

    ~magicException()
    {
        cout << "Destructor called." << endl;
        delete[] m_message;
    }

    char* getMessage()
    {
        return m_message;
    }
};

void someFunction()
{
    throw magicException("Bang!");
}

int main(int argc, char * argv[])
{
    try
    {
        someFunction();
    }
    catch (magicException& ex)
    {
        cout << ex.getMessage() << endl;
    }

    return 0;
}

具体来说,抛出的 magicException 对象的析构函数在 catch 块之前被调用。但是,如果我向我的类添加一个复制构造函数:

magicException(const magicException& other)
{
    cout << "Copy constructor called." << endl;
    m_message = new char[strlen(other.m_message) + 1];
    strcpy(m_message, other.m_message);
}

然后代码开始工作,析构函数在预期的位置(catch 块的末尾)被调用,但有趣的是复制构造函数仍然没有被调用。编译器是否对其进行了优化(Visual C++ 2008 关闭了优化),还是我遗漏了什么?

4

1 回答 1

4

具体来说,抛出的 magicException 对象的析构函数在 catch 块之前被调用。

是的,正如您从标准中引用的那样,编译器会获取一份副本,而原始的(可能)会被丢弃。您的问题是原始代码中缺少复制构造函数。但是,允许 C++ 编译器在各种情况下删除(或添加)复制构造函数调用,包括这种情况。

于 2010-01-23T09:56:35.483 回答