通过引用捕获的抛出对象的生命周期

发布于 2024-08-18 21:25:13 字数 1272 浏览 6 评论 0原文

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 关闭了优化),还是我遗漏了一些东西?

The C++ Standard, paragraph 15.1.4 sais:

The memory for the temporary copy of the exception being thrown is allocated in an unspecified way, except as noted in 3.7.3.1. The temporary persists as long as there is a handler being executed for that exception.

I'm wondering why this code crashes (I know that it's not best practice):

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;
}

Specifically, the destructor of the thrown magicException object gets called before the catch block. If I however add a copy constructor to my class:

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

Then the code works, the destructor gets called at the expected place (the end of the catch block), but interestingly the copy constructor still doesn't get called. Is it optimized away by the compiler (Visual C++ 2008 with optimizations turned off), or am I missing something?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

南街女流氓 2024-08-25 21:25:13

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

是的,正如您对标准的引用所说,编译器会获取副本,而原始文件(可能)会被丢弃。您的问题是原始代码中缺少复制构造函数。然而,C++ 编译器可以在各种情况下删除(或添加)复制构造函数调用,包括这种情况。

Specifically, the destructor of the
thrown magicException object gets
called before the catch block.

Yes, as your quote from the standard says, a copy is taken by the compiler, and the original (probably) discarded. Your problem is the lack of a copy constructor in your original code. However, a C++ compiler is allowed to remove (or add) copy constructor calls in all sorts of situations, including this one.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文