如何将带有自定义分配器的std :: vector传递给期望使用std :: allocator的函数?

时间:2017-07-06 15:23:02

标签: c++ vector boost allocator

我正在使用外部库(pcl),所以我需要一个不会改变现有函数原型的解决方案。

我正在使用的一个功能会生成std::vector<int, Eigen::aligned_allocator<int>>。我想要接下来调用的函数需要const boost::shared_ptr<std::vector<int, std::allocator<int>>>。我不想复制元素,因为它是我代码中已经很慢的关键部分。如果不是因为分配器不匹配,我只需执行以下操作即可解决shared_ptr要求:

// code that generates std::vector<int, Eigen::aligned_allocator<int>> source
boost::shared_ptr<std::vector<int>> indices(new std::vector<int>);
indices->swap(source);
// use indices as intended

这不能与MSVC编译器一起编译,因为它无法在这两种矢量类型之间进行转换。到目前为止,我所想到的唯一不会复制内容的解决方案是:

// code that generates std::vector<int, Eigen::aligned_allocator<int>> source
boost::shared_ptr<std::vector<int>> indices(new std::vector<int>);
indices->swap(reinterpret_cast<std::vector<int>&>(source));
// use indices as intended
indices->swap(reinterpret_cast<std::vector<int>&>(pcout.points));

注意我需要使用索引作为const shared_ptr。我相信分配器不会在交换操作中发挥作用。 int也应该不需要对齐任何填充,因为它们已经是32位大小。 std :: allocator版本应该能够从对齐版本中读取,因为它只能分配std :: allocator可能已经使用过的内存地址。最后,我换回来,因为如果尝试删除未对齐的保留空间,对齐的分配器可能会崩溃。

我尝试了它并没有崩溃,但这并不是要让我相信它确实是正确的。安全吗?如果没有,如果对编译器做出某些合理的假设,它是否有条件安全?有没有更明显影响性能的更安全的替代方案?

请不要回复&#34;描述您的代码&#34;,&#34;不值得&#34;或类似的答案。即使它们在这里适用,理论上也有一种情况,即复制不是一个可行的解决方案,这个线程应该解决这个问题。

Similar question正在谈论以清晰的方式复制数据,正如评论中所阐明的那样。

编辑:尽管Eigen :: aligned_allocator设计用于16位对齐,但是没有额外的填充添加到整数中。比较列表中第一个和最后一个元素的地址给出了元素数量和sizeof(int)的大小。这意味着int以一种应该与std :: allocator版本兼容的方式存储。我希望我今天晚些时候或在未来几天有时间做一个更完整的测试。

1 个答案:

答案 0 :(得分:2)

如果您能够将函数原型更改为另一种向量类型,那么标准库中有一个全新的命名空间(namespace pmr),它使用类型擦除来分配器,以确保使用不同的容器之间的兼容性分配器。

有关详情,请参阅polymorphic_allocator: when and why should I use it?

通过这种改变你可以做到

void foo(std::pmr::vector<int>& vec); 

并使用您想要的任何分配器传递矢量类型(只要它也是std::pmr::vector)。

如果您无法更改该功能所期望的矢量类型,那么我认为您可以比逐个复制/移动元素做得更好。

reinterpret_cast两个不同的矢量实例到不同的类型,然后使用它们的方法是非常危险的。