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

C++标准是否保证函数局部对象始终以右值引用返回?

工厂函数返回局部对象的右值保证与例外情况

我从工厂函数返回一个函数局部对象,想确认:C++标准是否在所有情况下都保证该对象会被当作右值处理?是否存在需要注意的例外场景?

示例代码

#include <cstdio>

template <typename T>
struct vectorlike
{
    vectorlike() = default;

    ~vectorlike() {
        if (ptr_) {
            delete ptr_;
        }
    }

    vectorlike(const vectorlike& other) {
        printf("%s(&) called!\n", __func__);
    }

    vectorlike(vectorlike&& other) {
        printf("%s(&&) called!\n", __func__);
    }

    auto operator=(const vectorlike& other) -> vectorlike& {
        printf("copy %s(&) called!\n", __func__);
        ptr_ = new T(*other.ptr_);
        return *this;
    }

    auto operator=(vectorlike&& other) noexcept -> vectorlike& {
        printf("move %s(&&) called!\n", __func__);
        ptr_ = other.ptr_;
        other.ptr_ = nullptr;
        return *this;
    }

    vectorlike(int i) {
        ptr_ = new T(i);
    }

    T* ptr_;
};

template <typename T>
auto vector_factory() {
    vectorlike<T> ret{2};

    return ret;
}

int main()
{
    vectorlike<int> hello;

    hello = vector_factory<int>();
}

运行输出

move operator=(&&) called!

核心规则说明

当函数返回非引用类型的局部对象时,C++标准有明确规则:

  1. 编译器优先进行返回值优化(RVO):直接在调用方的内存空间构造该局部对象,完全跳过拷贝/移动操作。
  2. 即使RVO未触发(比如手动禁用优化),标准要求将该局部对象转换为纯右值(prvalue),此时会优先匹配移动构造/移动赋值(如果类中定义了对应的操作)。你的示例中就是这种情况,返回的临时对象作为右值触发了移动赋值。

需要注意的例外场景

  • 返回引用类型:如果工厂函数声明为返回vectorlike<T>&,返回局部对象会导致悬垂引用(局部对象销毁后引用失效),属于未定义行为,且此时返回的是左值引用,不会被当作右值。
  • 显式使用std::move返回:若写return std::move(ret);,会强制将局部对象转为右值引用,但这会阻止RVO(RVO要求返回未被修改的局部命名对象),反而会触发移动构造,浪费优化机会。
  • 返回类型与局部对象类型不匹配:比如工厂函数返回Base类型,但局部对象是Derived(继承自Base),此时会先构造Derived对象,再隐式转换为Base临时对象(右值),但转换过程可能产生额外开销;若Base无移动构造,会退化为拷贝。
  • 局部对象是const限定的:如果定义const vectorlike<T> ret{2};,返回该对象时会被当作const右值,若类的移动操作是non-const的(如示例中的vectorlike(vectorlike&&)),则无法匹配移动操作,会触发拷贝构造/赋值。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 13:45:31