我正在使用一个外部库,它在某些时候给了我一个指向整数数组和大小的原始指针。
现在我想用 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_view
到 std::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::sort
、 std::find
、 std::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/