我想通过在将字符串返回到 What() 之前连接字符串来创建自定义异常。我知道还有其他方法可以达到想要的结果,我只是想了解为什么以下 3 段代码的行为不同。
class InvalidFormat : public std::exception
{
private:
std::string _exceptionValue;
public:
InvalidFormat(std::string str);
const char *what() const throw();
};
InvalidFormat::InvalidFormat(std::string str) : _exceptionValue(str) {}
const char *InvalidFormat::what() const throw() {
return ("Format is invalid => " + _exceptionValue).c_str();}
//doesn't output anything
InvalidFormat::InvalidFormat(std::string str) : _exceptionValue(str) {}
const char *InvalidFormat::what() const throw() {
return std::string("Format is invalid => ").assign(_exceptionValue).c_str();}
//outputs random data
InvalidFormat::InvalidFormat(std::string str) : _exceptionValue("Format is invalid => " + str) {}
const char *InvalidFormat::what() const throw() {
return _exceptionValue.c_str();}
//outputs is correct
以下代码对临时
c_str()
调用 std::string
,其生命在完整表达后结束(在 ;
):
return ("Format is invalid => " + _exceptionValue).c_str(); // UB-prone
当
InvalidFormat::what()
返回时,返回的指针指向已释放并消失的内存,这是未定义的行为。这再好不过了:
return std::string("Format is invalid => ").assign_exceptionValue).c_str(); // UB-prone
如果要返回指向它的非拥有指针,则必须存储连接结果:
InvalidFormat::InvalidFormat(std::string str)
: _exceptionValue("Format is invalid => " + str)
{}
const char *InvalidFormat::what() const throw()
{
return _exceptionValue.c_str(); // OK
}