根据C++标准,这是对临时安全的访问吗?

vsikbqxv  于 11个月前  发布在  其他
关注(0)|答案(1)|浏览(80)

我最近在一个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来解决这个问题,但是在定义上卡住了。我走到了:

  1. 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
  • 请引用相关标准规则,并解释标准版本之间的差异(如果有)。*
lymnna71

lymnna711#

这是很明确的。
12.2临时对象[class.temporary]
...临时对象被销毁,这是对完整表达式([intro.execution])求值的最后一步,完整表达式([intro.execution])(在词法上)包含临时对象的创建点。
1.9程序执行[介绍执行]
完整表达式是一个表达式,它不是另一个表达式的子表达式。
这里:

socket.SetPort(std::to_string(port).c_str());

字符串
临时对象是std::string对象,它是std::to_string的返回值。完整表达式是整个表达式。因此,临时对象-拥有其c_str()的对象-在调用SetPort()返回后被销毁。结束。
(此规则有两个例外,不适用于此)。

相关问题