在抛出异常时破坏弦乐临时演员

时间:2010-03-10 10:57:42

标签: c++ exception destructor temporary

请考虑以下代码:

std::string my_error_string = "Some error message";

// ...

throw std::runtime_error(std::string("Error: ") + my_error_string);

传递给runtime_error的字符串是字符串operator+返回的临时字符。假设此异常的处理方式如下:

catch (const std::runtime_error& e)
{
    std::cout << e.what() << std::endl;
}

字符串operator+返回的临时值何时被销毁?语言规范有什么可说的吗?另外,假设runtime_error接受了const char*参数,并抛出如下:

// Suppose runtime_error has the constructor runtime_error(const char* message)
throw std::runtime_error((std::string("Error: ") + my_error_string).c_str());

现在什么时候运营商+返回的临时字符串被销毁了?它会在catch块尝试打印之前被销毁,这就是为什么runtime_error接受std :: string而不是const char *?

3 个答案:

答案 0 :(得分:8)

runtime_error是一个包含字符串的类。该字符串将由普通的C ++构造和销毁机制为您管理。如果它包含char *,那么必须明确管理它,但你仍然不需要做任何事情作为runtime_error的用户

尽管你可能在互联网上的其他地方读过,但C ++几乎总是设计为“合理的东西” - 你实际上必须努力尝试打破这种合理的行为,当然这并非不可能。

答案 1 :(得分:5)

作为临时对象(12.2),+的结果将作为评估包含它的完整表达式(1.9 / 9)的最后一步而被销毁。在这种情况下,完整表达式 throw-expression

throw-expression 构造一个临时对象( exception-object )(15.1)(在本例中为std::runtime_error)。构建 exception-object 后, throw-expression 中的所有临时值都将被销毁。只有在 throw-expression 的评估完成后才抛出异常,因为临时的销毁是此评估的一部分,它们将在自输入try块以来构建的自动变量销毁之前被销毁(15.2)并在输入处理程序之前。

runtime_error构造函数的后置条件是what()返回strcmp认为等于传入参数返回的c_str()的内容。这是一个理论上的可能性,一旦作为构造函数参数传递的std::string被销毁,runtime_error的{​​{1}}可以返回不同的东西,尽管这将是一个有问题的实现,它仍然会有要成为某种类型的以null结尾的字符串,它无法返回指向死字符串陈旧what()的指针。

答案 2 :(得分:3)

请注意,runtime_error异常类会生成传递给构造函数的字符串的副本。因此,当您在异常对象上调用.what()时,您将无法获得传入的相同字符串实例。

所以为了回答你的问题,你所询问的临时内容会在包含它的表达式的“分号”处被破坏(这在你的第一个和第二个版本的问题中都是如此),但正如我所说,这不是那么有趣,因为已经制作了它的副本。