依据C++标准,临时std::string的c_str指针访问是否安全?
问题分析:std::to_string临时对象与c_str()的生命周期问题
结论
这段代码完全安全,不会触发未定义行为或访问已释放内存。
核心分析
先拆解代码的执行逻辑:
std::to_string(port)生成一个std::string类型的临时对象(prvalue)。- 对该临时对象调用
c_str(),得到指向其内部字符缓冲区的const char*指针。 - 指针被传入
SetPort函数,函数内部执行m_port = port;——这是调用std::string的赋值运算符,它会复制指针指向的全部字符内容到m_port的内部存储,而非保存指针本身。
临时对象生命周期的标准规则
根据C各版本标准(C98至C++23),临时对象的生命周期会延续到包含它的完整表达式结束时。这里的完整表达式就是整条socket.SetPort(std::to_string(port).c_str());语句。
也就是说:
- 在
SetPort函数执行期间,std::to_string生成的临时std::string对象始终处于存活状态,c_str()返回的指针指向的内存是有效的。 - 当
SetPort函数返回、整条语句执行完毕后,临时对象才会被销毁,但此时m_port已经完成了内容复制,不再依赖临时对象的内存,因此不存在悬空指针问题。
你之前的误解点在于认为c_str()需要延长临时对象生命周期,但实际上不需要——临时对象本身在完整表达式执行期间就足够存活,保证赋值操作的安全性。
UBSan未报错的原因
因为代码本身没有未定义行为,UBSan仅会在存在实际内存违规、未定义操作的场景下触发告警,所以此处无输出是正常的。
不同C++版本的差异
在所有C++版本中,该场景的规则完全一致:
- C98/C03:临时对象在完整表达式结束时销毁,赋值操作发生在临时对象存活期间,安全。
- C++11及以后:虽然prvalue的语义有调整,但临时对象的生命周期延长规则在该场景下未发生变化,同样保证临时对象存活至完整表达式结束,赋值操作安全有效。
注意事项
如果SetPort函数的逻辑是保存传入的const char*指针本身(而非复制内容到std::string),那才会导致未定义行为——临时对象销毁后指针悬空。但当前代码中std::string的赋值是复制内容,因此不存在这个风险。
内容的提问来源于stack exchange,提问作者jan.sende
相关产品推荐
相关产品推荐

