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

C++代码中移动临时Proxy与临时对象生命周期延长的合法性问询

关于C++移动临时对象与临时生命周期延长的问题
#include <iostream>
#include <array>

struct Matrix
{
    struct Proxy
    {
        Proxy(Matrix& m) : m_ { m } {}
        Proxy(Proxy&& rhs) : m_ { rhs.m_ }, a { std::move(rhs.a) }, index{rhs.index} {} // 1

        Proxy operator[](int i)
        {
            ++index;

            return { std::move(*this) };
        }

        Proxy& operator=(int value)
        {
            m_.v = value;

            return *this;
        }

        Matrix& m_;
        int     index = 0;

        std::array<int, 1000> a;
    };

    Proxy operator[](int index)
    {
        return { *this };
    }

    int v = -1;
};

int main()
{
    Matrix      m;
    const auto& q = m[1][2][3]; // 2
    std::cout << q.index << std::endl;
    std::cout << q.m_.v << std::endl;
}

问题1:代码(1)的移动构造函数用法是否合规,有无未定义行为?

完全符合C++规则,不存在未定义行为风险:

  • 移动构造函数Proxy(Proxy&& rhs)接收右值引用,临时Proxy对象本身就是右值,能合法绑定到右值引用参数,这是C++移动语义的标准用法。
  • 移动过程中:
    • m_是对原Matrix对象的引用,这里只是复制引用别名,而main里的Matrix m生命周期远长于所有临时Proxy,不会出现悬空引用。
    • std::move(rhs.a)是对std::array的移动操作,虽然std::array的移动构造实际是逐元素拷贝(固定大小栈分配容器特性),但完全合法;移动后原rhs.a处于“有效但未指定”状态,但rhs是临时对象,移动后立即销毁,不会再被使用,无风险。
  • 移动临时对象是C++标准明确允许的操作,核心就是接管临时对象资源以避免冗余拷贝,这里的用法完全符合设计意图。

问题2:代码(2)中临时对象的生命周期延长是否有保证?

有明确的标准保证,临时对象的生命周期会被延长至引用q的生命周期结束:

  • 根据C标准(如C20 §6.7.7),当临时对象被绑定到const左值引用(或右值引用)时,临时对象的生命周期会被延长,直到该引用的生命周期结束。
  • m[1][2][3]的最终结果是一个临时Proxy对象,它被绑定到const auto& q,因此这个临时对象的生命周期会从“当前全表达式结束”延长到main函数结束(即q销毁时)。
  • 链式调用中每一步的临时Proxy会被移动到下一个临时对象,但最终绑定到q的是最后一个临时对象,生命周期延长规则作用于这个最终对象,整个过程安全。

隐藏陷阱检查

这段代码不存在悬空引用或未定义行为:

  • q.m_绑定的是main中的Matrix m,m的生命周期覆盖q的整个生命周期,引用不会悬空。
  • index是值类型,移动构造时直接拷贝,无引用/指针悬空问题。
  • std::array<int, 1000> a是值类型,移动操作安全,不会导致资源泄漏或悬空。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 12:57:04