使用std :: vector作为原始内存的视图 [英] Using std::vector as view on to raw memory
问题描述
我正在使用一个外部库,该库有时会给我一个指向整数和大小数组的原始指针.
I'm using a external library which at some point gives me a raw pointer to an array of integers and a size.
现在,我想使用 std :: vector
来就地访问和修改这些值,而不是使用原始指针来访问它们.
Now I'd like to use std::vector
to access and modify these values in place, rather than accessing them with raw pointers.
以下是一个人工例子,可以解释这一点:
Here is an articifial example that explains the point:
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>
中的算法(排序,交换元素等).
The reason is that I need to apply algorithms from <algorithm>
(sorting, swaping elements etc.) on that data.
另一方面,更改该矢量的大小永远不会更改,因此不需要 push_back
, erase
, insert
在那个向量上.
On the other hand changing the size of that vector would never be changed, so push_back
, erase
, insert
are not required to work on that vector.
我可以基于库中的数据构造一个向量,使用修改该向量并将数据复制回库中,但这是我要避免的两个完整副本,因为该数据集可能确实是大.
I could construct a vector based on the data from the library, use modify that vector and copying the data back to to library, but that would be two complete copies that I'd like to avoid as the data set could be really big.
推荐答案
问题是 std :: vector
必须从初始化它的数组中复制元素,因为它具有它包含的对象的所有权.
The problem is that std::vector
has to make a copy of the elements from the array you initialize it with as it has the ownership of the objects it contains.
为避免这种情况,可以对数组使用 slice 对象(即类似于 std :: string_view
对 std :: string
).您可以编写自己的 array_view
类模板实现,其实例是通过使用指向数组第一个元素和数组长度的原始指针构造的:
To avoid this, you can use a slice object for an array (i.e., similar to what std::string_view
is to std::string
). You could write your own array_view
class template implementation whose instances are constructed by taking a raw pointer to an array's first element and the array length:
#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
doesn't store an array; it just holds a pointer to the beginning of the array and the length of that array. Therefore, array_view
objects are cheap to construct and to copy.
由于 array_view
提供了 begin()
和 end()
成员函数,因此您可以使用标准库算法(例如,> std :: sort
, std :: find
, std :: lower_bound
等)
Since array_view
provides the begin()
and end()
member functions, you can use the standard library algorithms (e.g., std::sort
, std::find
, std::lower_bound
, etc.) on it:
#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
)
上面的实现公开了 slice对象背后的概念.但是,从C ++ 20开始,您可以直接使用 std :: span
.在任何情况下,自C ++ 14起,您都可以使用 gsl :: span
Use std::span
(or gsl::span
) instead
The implementation above exposes the concept behind slice objects. However, since C++20 you can directly use std::span
instead. In any case, you can use gsl::span
since C++14.
这篇关于使用std :: vector作为原始内存的视图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!