从原始数据就地创建 std::vector
Create std::vector in-place from raw data
给定一个原始元素数组,如何创建一个在不重新分配和复制的情况下获得原始数组所有权的std::vector
?
例如,具有原始数组:
int* elems = new int[33]
如何创建指向elems
的大小33
std::vector
?
我确信从理论上讲这是可能的,因为通常std::vector
被实现为包含三个指针的结构,一个指向分配内存的开头,一个指向有效元素的末尾,一个指向分配内存的末尾。但是有没有使用原始数组初始化std::vector
结构的标准方法?
你需要的是一个"视图"而不是一个容器。容器拥有自己的元素,它们的主要目的是封装它们管理的原始内存。如果您需要自己管理内存,则不需要容器。看看如果你有string
,那将是你的解决方案string_view
。也许您可以应用增强范围。来自文档(强调我的):
范围概念的动机是有许多有用的 不满足 容器,以及许多可以用这个减少的算法来编写 一组要求。特别是,范围不一定
- 拥有可以通过它访问的元素,
- 具有复制语义,
PS:实际上std::array_view
被考虑为C++17,但不幸的是它没有进入标准。
这不能直接实现的原因是标准库使用分配器为容器保留内存。
因此,如果你有一个使用某种类型的分配器的std::vector
,并给它一些你创建的指针,你有效地打破了分配器习惯用法。例如,如果你的标准库的实现使用malloc
和free
而不是new
和delete
,你的程序将失败。
要使这成为一种标准方式,标准库需要提供一个接受T*
的构造函数,该该必须由向量稍后使用的同一分配器返回。因此,您需要的构造函数的签名类似于std::vector::vector(T* data, size_type used_elements, size_type capacity, const Allocator& alloc)
.请注意,分配器参数是必需的,因为T*
必须(理论上)由向量中使用的完全相同的分配器返回。
你可以通过根据这个概念创建自己的分配器来实现一些功能,但是要让你的33
元素不被重建,你还必须提供一个allocator::construct(..)
函数,这是一个无操作的函数,直到34th
元素(独占)。此外,您还必须首先将矢量大小调整为33
元素,以强制矢量具有正确的大小。
话虽如此,这仍然是一个坏主意,因为对于条件构造和分配函数,您可能会有更多的开销,而不是复制一次元素。
根据这一点,没有接受指向数据的指针的构造函数。因此,您不能将原始数组的所有权传递给矢量。
您只能创建矢量并将数据放入其中。
如果您正在处理的对象类型是可移动的,则可以执行以下操作:
template<typename T>
std::vector<std::unique_ptr<T>> ConvertArrayToVector(T* data, size_t size)
{
std::vector<std::unique_ptr<T>> result(size);
for (unsigned int i = 0; i<size; ++i)
result[i] = std::make_unique<T>(std::forward<T>(data[i]));
return result;
}
生成的向量现在拥有数组,从某种意义上说,它存储指向其元素的指针,并确保在销毁向量时删除对象,但原始数组在此过程中失效。
给定一个原始的元素数组,如何创建一个
std::vector
在不重新分配和复制的情况下获得原始数组的所有权?
没有办法。
如何创建大小为 33 的指向 ELEMS 的
std::vector
?
不可能的。
我相信从理论上讲这是可能的,
不,不是。
但是有没有使用原始数组初始化
std::vector
结构的标准方法?
不。
话虽如此,您有可能使用自定义分配器将解决方案组合在一起。但是,除了编写自定义分配器是一种很少使用且容易出错的技术这一事实之外,您不应高估此类解决方案的可用性。
std::vector<int>
和std::vector<int, MyAllocator>
是两个不同的类。如果您的目标是与需要std::vector<int>
的代码进行交互,则不能使用std::vector<int, MyAllocator>
;如果您打算在代码中创建和使用std::vector<int, MyAllocator>
,那么老实说,您最好只实现自己的非拥有容器类,即类似于自定义VectorView<T>
的东西。
- 使用std::vector的OpenCL矩阵乘法
- POCO::PostgreSQL:如何将std::vector支持添加到`Binder::bind`
- std::vector的包装器,使数组的结构看起来像结构的数组
- 编译器如何区分std::vector的构造函数
- 使用 pqxx 将 std::vector 存储在 postgresql 中,并从数据库中检索它
- 在std::vector上存储带有模板的类实例
- 在main()之外初始化std::vector会导致性能下降(多线程)
- 为什么std::vector比数组慢
- std::vector::迭代器是否可以合法地作为指针
- 如何将二进制格式的 C++ 对象的 std::vector 保存到磁盘?
- 为什么std::vector和std::valarray初始化构造函数不同
- ";结果类型必须是可从输入范围的值类型""构造的;创建std::vector时
- 在没有未定义行为的情况下实现类似std::vector的容器
- 如何调整 std::vector of Eigen::MatrixXd 的大小
- 使用 std::vector::reverse_iterator 将 int 序列化为字节向量?
- 如何将AERT_Allocate与 std:vector 一起使用
- 推导 std::vector::back() 的返回类型
- 如何将原始字节附加到 std::vector?
- std::vector 没有重载函数的实例与参数列表匹配
- 如果 KEY 是 std::list 或 std::vector 而不是值,那么 std::map 的默认行为是什么?