You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++函数参数临时对象销毁时机及代码崩溃问题咨询

C++临时对象生命周期与代码崩溃问题解答

简短版问题

如下代码中:

QString dataStr;

myfunc(dataStr.toUtf8().constData());

toUtf8()创建的临时QByteArray对象是在进入myfunc()作用域前销毁,还是会被保证在myfunc()调用结束后才销毁?

详细版背景

我正在维护一段类似如下的代码:

class Request
{
public :
    std::function<void()> requestFunc;
};

void myfunc(const char* data)
{
    auto request = new Request();

    auto lambda = [](const std::string& str)
    {
        cout << str;
    };
    // 使用data
    request->requestFunc = std::bind(std::move(lambda), std::string(data));
    requestQueue.push(std::move(request));
}

QString dataStr;

myfunc(dataStr.toUtf8().constData());

// 一段时间后,requestQueue被处理,requestFunc被调用

一位同事的机器上出现了崩溃问题。我们通过显式修改toUtf8()创建的临时QByteArray对象的作用域解决了该问题:

...
QString dataStr;

const QByteArray tempObj = dataStr.toUtf8();
myfunc(tempObj.constData());

问题得到解决,但之后我们与另一位同事讨论时,我并不清楚C++标准/编译器是否会保证临时对象存活至函数调用结束,还是其作用域仅限于参数,导致进入myfunc()后临时对象已被销毁。

我总结了两种能解释该“修复”的可能性:

  • 临时对象确实在进入函数前就已销毁,此时constData()指向已释放的内存。由于使用前没有过多操作,内存通常仍保留正确值且未被覆盖,这就是为什么多数情况下代码能正常运行,而修改后的版本是正确的修复方案。
  • 临时对象仅在函数调用结束后才销毁。这意味着bug出在其他地方,该“修复”只是延迟了临时对象的销毁,从而降低了已释放内存被覆盖的概率。

如果是后一种情况,您知道bug可能出在哪里吗?

编辑补充:
后来发现问题出在我之前的代码上。修改前我是这样写的:

QString dataStr;
const char* dataPtr = dataStr.toUtf8().constData();
myfunc(dataPtr);

因此临时对象在调用myfunc()前就已被销毁。


核心解答

临时对象生命周期的C++标准规定

  1. 作为函数实参的临时对象:当临时对象直接作为函数调用的实参时,它的生命周期会被延长至整个函数调用表达式完成,也就是myfunc()执行完毕之后才会销毁。所以在myfunc(dataStr.toUtf8().constData());这行代码中,toUtf8()创建的临时QByteArray会存活到myfunc()执行结束,此时myfunc()内部使用data指针是安全的。
  2. 赋值给指针后的临时对象:如果像你补充的错误写法那样,把临时对象的constData()赋值给指针后再调用函数:
    const char* dataPtr = dataStr.toUtf8().constData();
    myfunc(dataPtr);
    
    这里toUtf8()返回的临时QByteArray在赋值语句结束时就会立即销毁(临时对象的生命周期仅覆盖它所在的完整表达式),导致dataPtr指向已释放的内存。后续调用myfunc()时使用该指针属于未定义行为,这就是崩溃的直接原因。

对两种可能性的分析

  • 你的第一种假设完全符合实际场景:错误写法中临时对象确实在myfunc()调用前就销毁了,显式保存QByteArray的修改方案是正确的——因为tempObj的生命周期会覆盖myfunc()的整个调用过程,甚至更长,确保constData()指向的内存始终有效。
  • 第二种假设的场景不成立:如果是直接用myfunc(dataStr.toUtf8().constData());的写法,临时对象会存活到函数调用结束,myfunc()内部用std::string(data)构造字符串时会复制内存内容,后续requestFunc调用的是绑定的std::string副本,和原临时对象无关,不会出现崩溃。

内容的提问来源于stack exchange,提问作者Mickaël C. Guimarães

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 08:08:21