基于右值容器创建一个视图

编程语言 2026-07-10
#include <iostream>
#include <vector>
#include <ranges>
#include <algorithm>

auto get_vec()
{
    return std::vector<int> { 1, 2, 3, 4, 5, 6, 7 };
}

int main()
{
    // 1) As expected, returns: std::ranges::dangling
    auto it = std::ranges::max_element(get_vec());

    // 2) Is lifetime extended for the view, or is it dangling (undefined behavior) 
    auto vw = get_vec() | std::ranges::views::take(3);

    // prints first 3 ints
    std::ranges::for_each(vw, [](const int &i) { std::cout << i << '\n'; });
}

在语句1中,返回的类型是 ranges::dangling。这似乎是正确的,因为 get_vec() 返回一个 rvalue,因此迭代器指向一个已经不存在的值,即悬空。

出于同样的原因,我也预期在语句2中会有未定义行为,因为视图基于同一个右值返回对象。然而,它运行良好,我在 valgrindlibasan 上也没有发现问题。

这段代码会触发未定义行为吗?

编译器是 gcc 16.0.1

解决方案

这段代码是否会触发未定义行为?

不。这是定义明确的行为。

当pr值 vector 应用于范围适配器时,在应用之前它会被隐式转换为 owning_view,并且它的数据所有权会被转移给 owning_view

因此,vw 本身现在持有数据,并且不再悬空。

需要注意的是,owning_view 是一个只能移动的视图,因此你必须再次移动它以转移数据所有权:

auto vw = get_vec() | std::views::take(3);

auto vw2 =           vw  | std::views::take(5); // not ok
auto vw2 = std::move(vw) | std::views::take(5); // this is ok
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章