我使用的是一个外部库,它提供了一个具有以下接口的函数:
void foo(const std::vector<int>& data);
我从另一个已经分配的库中收到了一个非常大的C样式数组:
int* data = bar();
有没有什么方法可以在不分配和复制每个元素的情况下将data
传递给foo
?data
非常大,因此如果可能的话,我希望避免复制和分配。
我本可以使用分配器,但foo
不是分配器的模板,所以我认为这是不可能的。
我知道我可能在请求魔法,但如果可能的话,那就太好了。当然,如果foo
采用std::span
,这将不是问题。
魔术
这个答案很神奇,取决于编译器的实现。
我们可以强制访问矢量的容器。
以g++为例。它使用三个受保护的指针_M_start
、_M_finish
和_M_end_of_storage
来处理存储。因此,我们可以创建一个派生类,在构造函数和析构函数中设置/重置指向vaulebar()
返回的指针。
g++的示例代码:
static_assert(__GNUC__ == 7 && __GNUC_MINOR__ == 5 && __GNUC_PATCHLEVEL__ == 0);
class Dmy: public std::vector<int>
{
public:
Dmy(int *b, int *e)
{
_M_impl._M_start = b;
_M_impl._M_finish = e;
_M_impl._M_end_of_storage = _M_impl._M_finish;
}
~Dmy()
{
_M_impl._M_start = 0;
_M_impl._M_finish = 0;
_M_impl._M_end_of_storage = 0;
}
};
foo(Dmy(data, end_of_data));
有什么方法可以在不分配和复制每个元素的情况下将数据传递给foo吗?
不,在这个前提下,没有办法避免它。
通过更改前提有两种替代解决方案:
- 更改其他库以返回向量
- 将
foo
更改为不需要矢量。正如您所指出的,std::span
可能是一个合理的选择