请考虑以下代码:
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 *?
答案 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()时,您将无法获得传入的相同字符串实例。
所以为了回答你的问题,你所询问的临时内容会在包含它的表达式的“分号”处被破坏(这在你的第一个和第二个版本的问题中都是如此),但正如我所说,这不是那么有趣,因为已经制作了它的副本。