C++ 在抛出的异常中销毁字符串临时变量

C++ 在抛出的异常中销毁字符串临时变量,c++,exception,destructor,temporary,C++,Exception,Destructor,Temporary,考虑以下代码: std::string my_error_string = "Some error message"; // ... throw std::runtime_error(std::string("Error: ") + my_error_string); 传递到运行时\u错误的字符串是字符串的运算符+返回的临时字符串。假设此异常的处理方式如下: catch (const std::runtime_error& e) { std::cout << e

考虑以下代码:

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

// ...

throw std::runtime_error(std::string("Error: ") + my_error_string);
传递到运行时\u错误的字符串是字符串的
运算符+
返回的临时字符串。假设此异常的处理方式如下:

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

现在运算符+返回的临时字符串何时被销毁?它会在catch块尝试打印它之前被销毁吗?这就是为什么runtime\u error接受std::string而不是const char*?

runtime\u error是一个包含字符串的类。该字符串将由正常C++构造和销毁机制管理。如果它包含一个char*,那么就必须显式地管理它,但您仍然不必作为运行时错误的用户做任何事情


尽管你可以在互联网上看到其他地方,C++的设计几乎总是做“合理的事情”——你实际上必须非常努力地去打破这个合理的行为,当然当然也不是不可能的。

< P>注意,RunTimeObjultExtror异常类制作了一个拷贝到构造函数的字符串副本。因此,当您在exception对象上调用.what()时,您不会返回与传入的字符串实例完全相同的字符串实例

所以为了回答你的问题,你要问的临时对象会在包含它的表达式的“分号”处被销毁(在你的第一个和第二个问题版本中都是这样),但正如我所说的,这并没有那么有趣,因为它已经被复制了。

作为临时对象(12.2),
+
的结果将作为包含它的完整表达式(1.9/9)求值的最后一步被销毁。在本例中,完整表达式是抛出表达式

抛出表达式构造一个临时对象(异常对象)(15.1)(
std::runtime\u error
)。在构造exception对象之后,抛出表达式中的所有临时对象都将被销毁。只有在完成对抛出表达式的求值后才会抛出异常,因为临时变量的销毁是此求值的一部分,它们将在销毁自输入try块(15.2)以来构造的自动变量之前以及在输入处理程序之前被销毁


runtime\u error
构造函数的post条件是
what()
返回的内容
strcmp
认为与传入参数返回的内容
c\u str()
相等。从理论上讲,一旦作为构造函数参数传递的
std::string
被销毁,
runtime\u error
what()
可能会返回一些不同的结果,尽管这是一个有问题的实现,它仍然必须是某种以null结尾的字符串,它无法返回指向失效字符串的过时
c\u str()

挑剔:
std::runtime\u error(“error:+my\u error\u string”)可以,因为
my\u error\u string
的类型为string。你不必显式地调用
std::string
构造函数,在
“Error:”
上混乱你的代码。我更喜欢
std::string(“Error:”)。append(my_Error_string)
来回答销毁问题:只要
std::runtime_Error
对象存在,创建的临时对象就会被销毁(即,它的构造函数成功终止)。当然,对象有它的副本,所以这无关紧要;)
// Suppose runtime_error has the constructor runtime_error(const char* message)
throw std::runtime_error((std::string("Error: ") + my_error_string).c_str());