使用给定的数组初始化 std::vector 而不使用 std::allocator
Initialize std::vector with given array without std::allocator
我正在使用一个外部库,它提供了一个具有以下接口的函数:
void foo(const std::vector<int>& data);
我从另一个已经分配的库收到一个非常大的 C 风格数组:
int* data = bar();
有什么方法可以让我在不分配和复制每个元素的情况下将 data
传递给 foo
吗? data
非常大,因此我想尽可能避免复制和分配。
我本可以使用分配器,但是 foo
没有为分配器模板化,所以我认为这是不可能的。
我知道我可能在寻求魔法,但如果可能的话那就太好了。当然,如果 foo
宁愿选择 std::span
这也不是问题。
Is there any way for me to pass on data to foo without allocating and copying each element?
不行,前提是没办法避免。
通过改变前提,有两种替代解决方法:
- 将其他库更改为 return 向量。
- 将
foo
更改为不需要向量。正如您所指出的,std::span
可能是一个合理的选择。
魔法
这个答案很神奇,取决于编译器的实现。
我们可以强行访问一个vector的容器
以g++为例。它使用三个受保护的指针 _M_start
、_M_finish
和 _M_end_of_storage
来处理存储。所以我们可以在构造函数和析构函数中创建一个派生的class,即sets/resets指向return of vaule bar()
的指针。
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));
我正在使用一个外部库,它提供了一个具有以下接口的函数:
void foo(const std::vector<int>& data);
我从另一个已经分配的库收到一个非常大的 C 风格数组:
int* data = bar();
有什么方法可以让我在不分配和复制每个元素的情况下将 data
传递给 foo
吗? data
非常大,因此我想尽可能避免复制和分配。
我本可以使用分配器,但是 foo
没有为分配器模板化,所以我认为这是不可能的。
我知道我可能在寻求魔法,但如果可能的话那就太好了。当然,如果 foo
宁愿选择 std::span
这也不是问题。
Is there any way for me to pass on data to foo without allocating and copying each element?
不行,前提是没办法避免。
通过改变前提,有两种替代解决方法:
- 将其他库更改为 return 向量。
- 将
foo
更改为不需要向量。正如您所指出的,std::span
可能是一个合理的选择。
魔法
这个答案很神奇,取决于编译器的实现。
我们可以强行访问一个vector的容器
以g++为例。它使用三个受保护的指针 _M_start
、_M_finish
和 _M_end_of_storage
来处理存储。所以我们可以在构造函数和析构函数中创建一个派生的class,即sets/resets指向return of vaule bar()
的指针。
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));