基于右值容器创建一个视图
#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中会有未定义行为,因为视图基于同一个右值返回对象。然而,它运行良好,我在 valgrind 和 libasan 上也没有发现问题。
这段代码会触发未定义行为吗?
编译器是 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导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。