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

如何避免传入的临时vector被std::ranges移动

问题分析与解决方法

核心原因

你遇到的是C++20范围库的设计行为:当std::views::all接收右值类型的非视图容器(比如你传入的临时vector)时,会通过std::ranges::owning_view接管容器所有权,这会触发容器的移动构造,导致原容器被清空。而你用std::forward<T>(ts)把右值参数转发给views::all,正好命中了这个逻辑。

解决办法

方案1:直接使用参数作为左值(最简洁)

修改视图创建代码,去掉std::forward<T>,直接使用参数ts:

template<std::ranges::viewable_range T>
auto foo(T&& ts) -> size_t
{
    auto moves_ts { ts | std::views::all };
    return ts.size();
}

转发引用的参数ts本身是左值(即使它的类型是右值引用),直接使用ts会让views::all生成std::ranges::ref_view——它只会引用容器,不会触发移动。不管你传入左值变量还是临时右值容器,原容器的状态都不会被改变。

方案2:显式转为左值引用(保留转发逻辑时用)

如果函数其他地方需要用到std::forward,可以显式把参数转为左值引用后再传给views::all:

template<std::ranges::viewable_range T>
auto foo(T&& ts) -> size_t
{
    // 转为左值引用,避免移动
    auto moves_ts { static_cast<T&>(ts) | std::views::all };
    // 如果不需要修改容器,也可以用const左值引用:
    // auto moves_ts { std::as_const(ts) | std::views::all };
    return ts.size();
}

这种方式同样能确保views::all拿到的是左值引用,不会触发owning_view的移动构造。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 08:32:09