我最近在一个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()
返回一个纯右值,从而创建一个临时对象。
1.对c_str()
的调用延长了临时对象的生存期。(At least since C++17, before I am not sure.)
1.从这里开始我不确定。似乎临时的生命周期在这里结束,使得对const char*
指针的访问未定义行为。然而,当我尝试通过clang的未定义行为消毒器运行代码时,没有发现任何问题... https://godbolt.org/z/EfcvePoWe
- 请引用相关标准规则,并解释标准版本之间的差异(如果有)。*
1条答案
按热度按时间lymnna711#
这是很明确的。
12.2临时对象[class.temporary]
...临时对象被销毁,这是对完整表达式([intro.execution])求值的最后一步,完整表达式([intro.execution])(在词法上)包含临时对象的创建点。
1.9程序执行[介绍执行]
完整表达式是一个表达式,它不是另一个表达式的子表达式。
这里:
字符串
临时对象是
std::string
对象,它是std::to_string
的返回值。完整表达式是整个表达式。因此,临时对象-拥有其c_str()
的对象-在调用SetPort()
返回后被销毁。结束。(此规则有两个例外,不适用于此)。