我最近在 C++ 代码库中发现了以下代码模式,我现在想知道根据 C++ 标准它是否安全。 (真正的代码通过几个函数层传递
const char*
指针,但我将其压缩为其基本形式。)
#include <string>
class NetworkSocket
{
public:
void SetPort(const char* port)
{
m_port = port;
}
private:
std::string m_port;
};
int main()
{
const int port = 42;
NetworkSocket socket = {};
socket.SetPort(std::to_string(port).c_str());
}
具体来说,我想知道对
SetPort()
的调用是否安全,或者我们是否正在调用未定义的行为,或者访问(可能)已删除的内存。
我尝试使用 cppreference 自己解决这个问题,但陷入了定义中。我到目前为止:
std::to_string()
返回一个prvalue,从而创建一个临时对象。c_str()
的调用延长了临时对象的生命周期。 (至少从 C++17 开始,在我不确定之前。)const char*
指针的访问成为未定义的行为。然而,当我尝试通过 clang 的未定义行为消毒器运行代码时,没有发现任何问题...... https://godbolt.org/z/EfcvePoWe请引用相关标准规则,并说明标准版本之间的差异(如有)。
这是明确定义的。
12.2 临时对象 [class.temporary]
... 临时对象被销毁作为评估完整的最后一步 表达式 ([intro.execution]) (词法上)包含以下点: 他们被创造了。
这里:
socket.SetPort(std::to_string(port).c_str());
临时对象是
std::string
对象,它是 std::to_string
的返回值。毫无疑问,完整的表达式就是整个表达式。因此,临时对象(拥有其 c_str()
的对象)在对 SetPort()
的调用返回后被销毁。结局。
(此规则有两个例外,它们不适用于此处)。