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

将右值传入函数后返回其引用,持有该引用是否存在风险?

问题

阅读某项目源码时发现一个有趣的写法:一个模板函数接收T&&参数,完成操作后返回T&。输入不是std::ostream这类全局/外部对象,而是本地创建的临时对象。我写了类似示例,能看到函数输入和输出的地址一致,但疑问是:当以function(T{})形式传入右值时,函数返回后持有该右值的地址,会不会存在问题?

#include <iostream>


auto println(auto&&...args) {

    ((std::cout << args), ...);

    std::cout << std::endl;
}

struct S {
    int value = 0;
};

S& foo(S& ins) {
    ins.value += 1;
    return ins;
}

const S& bar(const S& ins) {
    // nothing
    return ins;
}

S& zog(S&& ins) {
    println(std::hex, uintptr_t(&ins));
    return ins;
}

template <typename T>
T& kek(T&& param) {
    println(std::hex, uintptr_t(&param));
    return param;
}

int main() {
    S ins;
    println(std::hex, uintptr_t(&ins));
    println(std::hex, uintptr_t(&foo(ins)));
    println(std::hex, uintptr_t(&bar(ins)));

    // Ops
    S& s = zog(S{}); // RVO ? 
    println(std::hex, uintptr_t(&s));

    // lvalue
    int x = 0;
    // int& kek<int&>(int& param)...
    kek(x); 

    // const lvalue 
    const int y = 0;
    // const int& kek<const int&>(const int& param)... 
    kek(y);

    // rvalue
    // int& kek(int &&)... 
    int& temp = kek(0);
    // rvalue address still exists
    println(std::hex, uintptr_t(&temp));

    return 0;
}
解答

这确实会导致未定义行为,核心原因是临时对象的生命周期规则:

  • 当你传入S{}这类右值到函数时,这个临时对象的生命周期只持续到当前完整表达式结束。这里的完整表达式就是zog(S{})或者kek(0)这一行。
  • 函数里的参数ins(或param)是绑定到这个临时对象的引用,但临时对象本身在表达式结束后就会被销毁。此时你返回的引用就变成了悬垂引用——指向已经被释放的内存。
  • 你看到地址一致只是巧合:临时对象销毁后,内存地址暂时还没被覆盖,但访问这个地址的行为完全是未定义的,可能在不同编译器、优化等级下出现崩溃、乱码等各种问题。

针对代码细节补充:

  • 函数zog(S&& ins)和模板kek(T&& param)在传入右值时,param是右值引用,但它绑定的临时对象生命周期不会因为被引用而延长到函数返回之后。只有当临时对象直接绑定到函数外部的引用时(比如const S& s = S{}),生命周期才会延长到引用的生命周期结束,但你的情况是通过函数返回引用,这条规则不适用。
  • 测试中看到地址一致不代表对象还存活,这只是内存没有被立即重写的假象,属于未定义行为的“侥幸”表现,绝对不能依赖。

总结:这种写法是错误的,返回绑定到临时对象的引用会导致悬垂引用,后续任何通过该引用的操作都是未定义行为。如果需要返回操作后的对象,应该返回值而不是引用,或者确保传入的是生命周期足够长的左值。

内容的提问来源于stack exchange,提问作者user20059122

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 14:51:03