C ++标准,第15.1.4段sais:
抛出异常的临时副本的内存以未指定的方式分配,除非在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并关闭了优化),或者我错过了什么?
答案 0 :(得分:4)
具体来说,是析构函数 抛出magicException对象获取 在捕获块之前调用。
是的,正如您从标准中引用的那样,编译器会复制一份副本,并且原始(可能)被丢弃。您的问题是原始代码中缺少复制构造函数。但是,允许C ++编译器在各种情况下删除(或添加)复制构造函数调用,包括这种情况。