owning_view
类(C++ 标准库)
获取另一个区域中元素的所有权的视图。
语法
template<range R>
requires std::movable<R> && (!is-initializer-list<R>)
class owning_view : public ranges::view_interface<owning_view<R>>;
模板参数
R
基础范围的类型。
视图特征
有关下列条目的说明,请参阅视图类特征
特征 | 说明 |
---|---|
范围适配器 | views::all |
基础范围 | 必须满足 input_range 或更高范围 |
元素类型 | 与基础范围相同 |
视图迭代器类别 | 与基础范围相同 |
已设置大小 | 仅当基础范围满足 sized_range 要求时 |
是 const 可迭代 |
仅当基础范围满足 const-iterable 要求时 |
常见范围 | 仅当基础范围满足 common_range 要求时 |
借入范围 | 仅当基础范围满足 borrowed_range 要求时 |
成员
成员函数 | 描述 |
---|---|
构造函数 | 构造 owning_view 。 |
base C++20 |
获取对自有范围的引用。 |
begin C++20 |
获取指向第一个元素的迭代器。 |
data C++20 |
获取指向第一个元素的指针。 |
empty C++20 |
测试视图是否为空。 |
end C++20 |
获取视图末尾的 sentinel。 |
size C++20 |
获取元素数。 |
operator= |
将内容从另一个 owning_view 分配(移动)给此内容。 |
从 view_interface 继承 |
描述 |
back C++20 |
获取最后一个元素。 |
front C++20 |
获取第一个元素。 |
operator[] C++20 |
获取指定位置的元素。 |
operator bool C++20 |
测试视图是否不为空。 |
注解
创建 owning_view
的最佳方法是使用 views::all
范围适配器。 范围适配器是创建视图类的预期方法。 如果要创建自己的自定义视图类型,会公开视图类型。
尽管此类拥有其元素,但构造成本并不高,因为基础范围是使用 std::move()
移动的。
如果希望某个范围不依赖于提供元素的容器的生存期,则此视图非常有用。
要求
标头: <ranges>
(自C++20以来)
命名空间:std::ranges
编译器选项:/std:c++20
或更高版本是必需的。
构造函数
创建 owning_view
的实例。
1) owning_view() requires default_initializable<R> = default;
2) constexpr owning_view(R&& rg);
3) owning_view(const owning_view& v) = delete; // no copy constructor
4) owning_view(const owning_view&& v) = default; // move constructor
参数
rg
要移动到 owning_view
的范围。
v
要移动到新 owning_view
的 owning_view
。
有关模板参数类型的信息,请参阅模板参数。
备注
1) 默认构造函数创建默认初始化 owning_view
。
2) 移动从 rg
构造 owning_view
。
3) 无法复制 owning_view
,只能移动。
4) 从另一个 owning_view
构造 owning_view
。
示例: owning_view
// requires /std:c++20 or later
#include <ranges>
#include <iostream>
#include <vector>
#include <utility>
int main()
{
std::vector<int> v = {1,2,3,4,5,6,7,8,9,10};
auto myOwningView = std::views::all(std::move(v)); // create an owning_view from a moved vector
std::cout << v.size() << '\n'; // outputs 0 because myOwningView now owns the elements
std::cout << myOwningView.size() << '\n'; // outputs 10
std::vector<int> v2 = {1,2,3,4,5};
std::ranges::owning_view<std::vector<int>> ov2{std::move(v2)};
std::cout << v2.size() << '\n'; // outputs 0 because ov2 now owns the elements
std::cout << ov2.size() << '\n'; // outputs 5
}
0
10
0
5
base
获取对基础范围的引用。
1) constexpr R& base() & noexcept { return r_; }
2) constexpr const R& base() const & noexcept { return r_; }
3) constexpr R&& base() && noexcept { return std::move(r_); }
4) constexpr const R&& base() const && noexcept { return std::move(r_); }
参数
无。
返回值
对基础范围的引用,称之为 rg
。
对于 1 & 2,基础范围通过 return rg;
返回
对于 3 & 4,基础范围通过 std::move(rg);
返回
begin
获取指向视图中第一个元素的迭代器。
constexpr iterator_t<R> begin();
constexpr auto begin() const requires range<const R>;
参数
无。
返回值
指向视图中第一个元素的迭代器:
data
获取指向视图中第一个元素的指针。
constexpr auto data()
requires std::contiguous_iterator<ranges::iterator_t<R>>;
constexpr auto data() const
requires std::contiguous_iterator<ranges::iterator_t<const R>>;
参数
无。
返回值
指向视图中第一个元素的指针。
备注
基础拥有的范围必须满足 contiguous_range
。
empty
测试视图是否为空。
constexpr bool empty();
constexpr bool empty() const;
参数
无。
返回值
如果基础范围没有元素,则返回 true
。 否则返回 false
。
end
获取视图末尾的 sentinel。
constexpr sentinel_t<R> end();
constexpr auto end() const requires range<const R>
返回值
视图中最后一个元素后面的 sentinel:
size
获取视图中的元素数。
constexpr auto size() requires ranges::sized_range<R>;
constexpr auto size() const requires ranges::sized_range<const R>;
参数
无。
返回值
视图中的元素数。
operator=
将内容从另一个 owning_view
分配(移动)给此内容。
owning_view& operator=(owning_view&&) = default;
参数
要为此分配(移动)的 owning_view
。
返回值
*this
注解
无法复制 owning_view
,只能移动。
示例: operator=
// requires /std:c++20 or later
#include <ranges>
#include <iostream>
#include <vector>
int main()
{
std::vector<int> v1 = {1,2,3};
std::ranges::owning_view<std::vector<int>> ov1{std::move(v1)};
std::vector<int> v2 = {4,5,6};
std::ranges::owning_view<std::vector<int>> ov2{std::move(v2)};
// operator=
ov2 = std::move(ov1);
// ov1 took ownership of v1, so v1 is empty
// ov2 took ownership of v2, so v2 is empty
// ov2 then took ownership of ov1, so ov1 is empty
// ov2 now owns the elements 1, 2, 3
std::cout << std::boolalpha << "v1.empty():" << v1.empty() << " ov1.empty():" << ov1.empty() << '\n'; // v1.empty():true ov1.empty():true
std::cout << "v2.empty():" << v2.empty() << " ov2.size():" << ov2.size() << '\n'; // v2.empty():true ov2.size():3
for (auto e : ov2)
{
std::cout << e << ' '; // 1 2 3
}
}
v1.empty():true ov1.empty():true
v2.empty():true ov2.size():3
1 2 3