从std :: vector接管内存 [英] taking over memory from std::vector

查看:101
本文介绍了从std :: vector接管内存的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用一个处理大量数据的外部库。数据由原始指针加上长度传递。该库不声明指针的所有权,而是在处理完数据后调用提供的回调函数(具有两个相同的参数)。



数据已准备就绪通过使用 std :: vector< T> 方便,我宁愿不放弃这种便利。复制数据完全是不可能的。因此,我需要一种方法来接管 std :: vector< T> 所拥有的内存缓冲区,然后在回调中将其释放。 / p>

我当前的解决方案如下:

  std :: vector< &输入= prepare_input(); 
T *数据= input.data();
size_t size = input.size();
//将向量移至原始存储区,以防止释放
alignas(std :: vector< T>)char temp [sizeof(std :: vector< T>))];
new(temp)std :: vector< t(std :: move(input));
//调用库
lib :: startProcesing(data,size);

,然后在回调函数中:

  void回调(T * data,size_t size){
std :: allocator< T>()。deallocate(data,size);
}

此解决方案有效,因为标准分配器的 deallocate 函数将忽略其第二个参数(元素计数),仅调用 :: operator delete(data)。否则,可能会发生不好的事情,因为输入向量的大小可能比其容量



我的问题是:是否有一种可靠的(写成C ++标准)方式来接管 std :: vector的缓冲区并在以后的某个时间手动发布?

解决方案

您不能拥有此所有权向量中的内存,但是您可以用另一种方式解决您的潜在问题。



这里是我的处理方式-由于静态全局变量和不是线程安全的,但是可以通过对注册表对象的访问进行一些简单的锁定来实现。

 静态std :: map< T *,std :: vector< T> *>注册表
void my_startProcessing(std :: vector< T> *数据){
Registry.put(data-> data(),data);
lib :: startProcesing(data-> data(),data-> size());
}

void my_callback(T * data,size_t length){
std :: vector< T> *原始= Registry.get(数据);
删除原件;
registry.remove(数据);
}

现在您可以做

  std :: vector< T> *输入= ... 
my_startProcessing(输入);

但是要小心!如果添加/删除元素,将会发生不好的事情调用 my_startProcessing 后输入的内容-库的缓冲区可能无效。 (您可能被允许更改向量中的值,因为我相信它将正确地写入数据,但是这也取决于库允许的内容。)



如果 T = bool 也是无效的,因为 std :: vector< bool> ; :: data()不起作用。


I use an external library which operates on large quantities of data. The data is passed in by a raw pointer, plus the length. The library does not claim ownership of the pointer, but invokes a provided callback function (with the same two arguments) when it is done with the data.

The data gets prepared conveniently by using std::vector<T>, and I'd rather not give up this convenience. Copying the data is completely out of the question. Thus, I need a way to "take over" the memory buffer owned by an std::vector<T>, and (later on) deallocate it in the callback.

My current solution looks as follows:

std::vector<T> input = prepare_input();
T * data = input.data();
size_t size = input.size();
// move the vector to "raw" storage, to prevent deallocation
alignas(std::vector<T>) char temp[sizeof(std::vector<T>)];
new (temp) std::vector<T>(std::move(input));
// invoke the library
lib::startProcesing(data, size);

and, in the callback function:

void callback(T * data, size_t size) {
    std::allocator<T>().deallocate(data, size);
}

This solution works, because the standard allocator's deallocate function ignores its second argument (the element count) and simply calls ::operator delete(data). If it did not, bad things could happen, as the size of the input vector might be quite a bit smaller than its capacity.

My question is: is there a reliable (wrt. the C++ standard) way of taking over the buffer of std::vector and releasing it "manually" at some later time?

解决方案

You can't take ownership of the memory from a vector, but you can solve your underlying problem another way.

Here's how I'd approach it - its a bit hacky because of the static global variable and not thread safe, but it can be made so with some simple locking around accesses to the registry object.

static std::map<T*, std::vector<T>*> registry;
void my_startProcessing(std::vector<T> * data) {
  registry.put(data->data(), data);
  lib::startProcesing(data->data(), data->size());
}

void my_callback(T * data, size_t length) {
  std::vector<T> * original = registry.get(data);
  delete original;
  registry.remove(data);
}

Now you can just do

std::vector<T> * input = ...
my_startProcessing(input);

But watch out! Bad things will happen if you add/remove elements to the input after you've called my_startProcessing - the buffer the library has may be invalidated. (You may be allowed to change values in the vector, as I believe that will write through the to data correctly, but that will depend on what the library allows too.)

Also this doesn't work if T=bool since std::vector<bool>::data() doesn't work.

这篇关于从std :: vector接管内存的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆