C++98中string拼接与c_str()返回值的异常行为差异解析
自定义异常
what()方法三种实现的行为差异原因分析 首先是自定义异常类的定义:
class InvalidFormat : public std::exception { private: std::string _exceptionValue; public: InvalidFormat(std::string str); const char *what() const throw(); };
下面分别分析三段实现的行为差异:
案例1:无任何输出
InvalidFormat::InvalidFormat(std::string str) : _exceptionValue(str) {} const char *InvalidFormat::what() const throw() { return ("Format is invalid => " + _exceptionValue).c_str();}
原因:("Format is invalid => " + _exceptionValue)会创建一个临时std::string对象,c_str()返回的是该临时对象内部字符数组的地址。但临时对象会在return语句执行完成后立即被销毁,对应的内存被释放,返回的指针变成悬空指针。后续读取该指针指向的内存时,已经没有有效数据,因此无任何输出。
案例2:输出随机数据
InvalidFormat::InvalidFormat(std::string str) : _exceptionValue(str) {} const char *InvalidFormat::what() const throw() { return std::string("Format is invalid => ").assign(_exceptionValue).c_str();}
原因:std::string("Format is invalid => ").assign(_exceptionValue)同样生成了临时std::string对象,assign()只是替换了这个临时对象的内容,c_str()返回的依旧是临时对象的内部指针。临时对象在return后被销毁,指针悬空。此时该内存区域可能已被其他程序数据覆盖,所以读取到的是随机垃圾数据。
案例3:输出结果正确
InvalidFormat::InvalidFormat(std::string str) : _exceptionValue("Format is invalid => " + str) {} const char *InvalidFormat::what() const throw() { return _exceptionValue.c_str();}
原因:构造阶段就把拼接完成的字符串存储到了类的成员变量_exceptionValue中。what()返回的是成员变量的c_str()指针,而成员变量的生命周期和异常对象完全一致,只要异常对象未被销毁,该指针就始终指向有效的内存区域,因此能正确输出拼接后的内容。
内容的提问来源于stack exchange,提问作者Ethan G.
相关产品推荐
相关产品推荐

