抛出异常时破坏字符串临时值
考虑以下代码:
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());
现在,operator+ 返回的临时字符串何时被销毁?它会在 catch 块尝试打印它之前被销毁吗?这就是为什么 runtime_error 接受 std::string 而不是 const char* 的原因吗?
Consider the following code:
std::string my_error_string = "Some error message";
// ...
throw std::runtime_error(std::string("Error: ") + my_error_string);
The string passed to runtime_error is a temporary returned by string's operator+
. Suppose this exception is handled something like:
catch (const std::runtime_error& e)
{
std::cout << e.what() << std::endl;
}
When is the temporary returned by string's operator+
destroyed? Does the language spec have anything to say about this? Also, suppose runtime_error took a const char*
argument and was thrown like this:
// Suppose runtime_error has the constructor runtime_error(const char* message)
throw std::runtime_error((std::string("Error: ") + my_error_string).c_str());
Now when is the temporary string returned by operator+ destroyed? Would it be destroyed before the catch block tries to print it, and is this why runtime_error accepts a std::string and not a const char*?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
runtime_error 是一个包含字符串的类。该字符串将由正常的 C++ 构造和销毁机制为您管理。如果它包含一个 char *,那么就必须显式管理它,但您仍然不必作为运行时错误的用户执行任何操作。
不管你在互联网上其他地方读到了什么,C++ 的设计几乎总是做“合理的事情”——你实际上必须相当努力地尝试打破这种合理的行为,尽管当然这并非不可能。
runtime_error is a class which contains a string. That string will be managed for you by the normal C++ construction and destruction mechanisms. If it contained a char *, then that would have to be explicitly managed, but you would still not have to do anything as a user of runtime_error.
Despite what you may read elsewhere on the internet, C++ is designed to almost always do "the reasonable thing" - you actually have to try fairly hard to break this reasonable behaviour, though of course it is not impossible to do so.
作为临时对象 (12.2),
+
的结果将在包含它的完整表达式 (1.9/9) 求值的最后一步被销毁。在这种情况下,完整表达式是抛出表达式。抛出表达式构造一个临时对象(异常对象)(15.1)(在本例中是
std::runtime_error
)。 异常对象构造完成后,抛出表达式中的所有临时对象都将被销毁。仅当抛出表达式的求值完成后才会抛出异常,因为临时变量的销毁是此求值的一部分,它们将在销毁自进入 try 块以来构造的自动变量之前被销毁(15.2) 以及在输入处理程序之前。runtime_error
构造函数的后置条件是what()
返回strcmp
认为等于c_str()< 的内容/code> 传入的参数返回。理论上,一旦作为构造函数参数传递的
std::string
被销毁,runtime_error
的what()
可能会返回一些东西不同的是,尽管这将是一个有问题的实现,并且它仍然必须是某种以 null 结尾的字符串,但它无法返回指向死字符串的陈旧c_str()
的指针。As a temporary object (12.2), the result of the
+
will be destroyed as the last step in the evaluation of the full-expression (1.9/9) that contains it. In this case the full-expression is the throw-expression.A throw-expression constructs a temporary object (the exception-object) (15.1) (
std::runtime_error
in this case). All the temporaries in the throw-expression will be destroyed after the exception-object has been constructed. The exception is thrown only once the evaluation of the throw-expression has completed, as the destruction of temporaries is part of this evaluation they will be destroyed before the destruction of automatic variables constructed since the try block was entered (15.2) and before the handler is entered.The post-condition on
runtime_error
's constructor is thatwhat()
returns something thatstrcmp
considers equal to whatc_str()
on the passed in argument returns. It is a theoretical possiblility that once thestd::string
passed as a constructor argument is destroyed,runtime_error
'swhat()
could return something different, although it would be a questionable implementation and it would still have to be a null-terminated string of some sort, it couldn't return a pointer to a stalec_str()
of a dead string.请注意,runtime_error 异常类会复制传递到构造函数中的字符串。因此,当您在异常对象上调用 .what() 时,您不会返回传入的完全相同的字符串实例。
因此,为了回答您的问题,您要询问的临时对象会在“分号处”被销毁包含它的表达式的(这在问题的第一个和第二个版本中都是如此),但正如我所说,这并不是那么有趣,因为已经制作了它的副本。
Note that the runtime_error exception class makes a copy of the string passed into the constructor. So when you're calling .what() on the exception object, you're not getting back the same exact string instance you passed in.
So to answer your question, the temporary you're asking about gets destroyed "at the semicolon" of the expression that contains it (this is true in both your first and second version of the question), but as I said, this isn't that interesting, because a copy of it was already made.