C++抛出绑定临时值的引用是否属于未定义行为?
关于抛出携带动态字符串异常的合法性说明
各测试场景的行为判定
undefined_behavior()属于明确的未定义行为:函数返回绑定到临时std::string的const引用,临时对象在函数返回调用点前就已销毁,返回的是悬垂引用,访问该引用触发段错误是典型表现。test()属于完全合规的标准行为,不存在未定义:- 标准库所有异常类的构造函数虽然形参是
const std::string&,但实现要求必须拷贝传入的字符串内容,异常对象内部持有独立的字符串副本,不会保留对外部传入字符串的引用。 - 构造
std::runtime_error时传入的拼接临时字符串,会在构造函数执行期间完成拷贝,后续临时对象销毁不影响异常对象的内部状态。 - C++标准规定throw语句创建的异常对象会存放在独立的异常存储区,生命周期持续到对应catch块执行完毕,和抛出点所在作用域的局部变量、临时对象的生命周期完全独立。
- 标准库所有异常类的构造函数虽然形参是
test2()同样属于完全合规的标准行为:- throw语句的操作数如果是引用类型,会先拷贝/移动引用指向的对象,在异常存储区生成独立的异常对象,不会直接抛出引用本身。
- 局部引用
ref绑定的临时字符串生命周期持续到test2()函数作用域结束,完全覆盖throw执行时的拷贝流程,拷贝完成后原临时对象随函数栈销毁,异常存储区的独立对象不受影响,catch块绑定的引用指向的是异常存储区的对象,不存在悬垂问题。
抛出动态消息异常的正确实现
你当前使用的throw std::runtime_error("Temporary" + std::to_string(100));写法本身就是标准合规的正确写法,无需调整。如果需要拼接更复杂的错误消息,也可以先构造局部字符串对象再传入异常构造函数,效果完全一致:
void throw_with_code(int err_code) { std::string err_msg = "请求处理失败,错误码:"; err_msg += std::to_string(err_code); err_msg += ",请确认网络连接与权限配置"; throw std::runtime_error(err_msg); }
避坑提示:自定义异常类时,不要仅保存传入字符串的引用或指针而不做拷贝,这类自定义实现才会触发悬垂引用问题,标准库异常类不存在该设计缺陷。
内容的提问来源于stack exchange,提问作者Winter
相关产品推荐
相关产品推荐

