c++ - 使用 std::vector 作为原始内存的 View

标签 c++ c++11 vector stdvector

我正在使用一个外部库,它在某些时候给了我一个指向整数数组和大小的原始指针。

现在我想用 std::vector就地访问和修改这些值,而不是使用原始指针访问它们。

这是一个解释这一点的人为示例:

size_t size = 0;
int * data = get_data_from_library(size);   // raw data from library {5,3,2,1,4}, size gets filled in

std::vector<int> v = ????;                  // pseudo vector to be used to access the raw data

std::sort(v.begin(), v.end());              // sort raw data in place

for (int i = 0; i < 5; i++)
{
  std::cout << data[i] << "\n";             // display sorted raw data 
}

预期输出:
1
2
3
4
5

原因是我需要应用来自 <algorithm> 的算法(排序,交换元素等)在该数据上。

另一方面,改变 vector 的大小永远不会改变,所以 push_back , erase , insert不需要处理该 vector 。

我可以根据库中的数据构建一个 vector ,使用修改该 vector 并将数据复制回库,但这将是我想避免的两个完整拷贝,因为数据集可能非常大。

最佳答案

问题是std::vector必须从初始化它的数组中复制元素,因为它拥有它包含的对象的所有权。

为避免这种情况,您可以对数组使用切片对象(即,类似于 std::string_viewstd::string 的内容)。你可以自己写 array_view类模板实现,其实例是通过获取指向数组第一个元素的原始指针和数组长度来构造的:

#include <cstdint>

template<typename T>
class array_view {
   T* ptr_;
   std::size_t len_;
public:
   array_view(T* ptr, std::size_t len) noexcept: ptr_{ptr}, len_{len} {}

   T& operator[](int i) noexcept { return ptr_[i]; }
   T const& operator[](int i) const noexcept { return ptr_[i]; }
   auto size() const noexcept { return len_; }

   auto begin() noexcept { return ptr_; }
   auto end() noexcept { return ptr_ + len_; }
};
array_view不存储数组;它只保存一个指向数组开头和数组长度的指针。因此,array_view对象的构建和复制成本很低。

array_view提供 begin()end()成员函数,您可以在其上使用标准库算法(例如, std::sortstd::findstd::lower_bound 等):
#define LEN 5

auto main() -> int {
   int arr[LEN] = {4, 5, 1, 2, 3};

   array_view<int> av(arr, LEN);

   std::sort(av.begin(), av.end());

   for (auto const& val: av)
      std::cout << val << ' ';
   std::cout << '\n';
}

输出:
1 2 3 4 5

使用 std::span (或 gsl::span )代替

上面的实现揭示了切片对象背后的概念。但是,从 C++20 开始,您可以直接使用 std::span 相反。在任何情况下,您都可以使用 gsl::span 从 C++14 开始。

关于c++ - 使用 std::vector 作为原始内存的 View ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60151514/

相关文章:

c++ - `typename = enable_if_t<...>` 和 `enable_if_t<...,bool> = true` 之间的区别

c++ - 多字节字符 '\377777' 是如何工作的?

c++ - 如何比较 vector 和数组?

Java:在两个类之间共享 vector

c++ - 如何在没有 reinterpret_cast 的情况下将 unsigned char* 输出到文件

c++ - 如何删除我提供透明背景图像的 QDialog 的边框?

c++ - 为什么 "Multiple definitions linker error"当 nm 只看到一个定义

c++ - 将 vector 分配给多重集

c++ - 编译器无法推断出可变参数模板的模板参数

c++ - 声明一个非常大的整数 vector ?