【发布时间】:2015-01-25 11:27:48
【问题描述】:
我使用一个对大量数据进行操作的外部库。数据由原始指针传入,加上长度。库不声明指针的所有权,但在处理完数据后调用提供的回调函数(具有相同的两个参数)。
使用std::vector<T> 可以方便地准备数据,我不想放弃这种方便。复制数据是完全不可能的。因此,我需要一种方法来“接管”std::vector<T> 拥有的内存缓冲区,并(稍后)在回调中释放它。
我目前的解决方案如下:
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);
并且,在回调函数中:
void callback(T * data, size_t size) {
std::allocator<T>().deallocate(data, size);
}
此解决方案有效,因为标准分配器的deallocate 函数忽略了它的第二个参数(元素计数)并简单地调用::operator delete(data)。如果没有,可能会发生不好的事情,因为输入向量的size 可能比它的capacity 小很多。
我的问题是:是否有一种可靠的(按照 C++ 标准)方式来接管 std::vector 的缓冲区并在以后“手动”释放它?
【问题讨论】:
-
你需要接管整个向量。
-
如果
vector有一个detach函数会很好......但它没有 -
@T.C.:但我没有地方可以存储它——输入产生和释放发生在程序的两个不同部分
-
我不明白对齐存储的需求。为什么不只是
unique_ptr<vector<T>> temp(new vector<T>(move(input)));?此外,您的解决方案仅在T是一种可简单破坏的类型时才有效,否则您需要在每个元素上调用allocator<T>::destroy。要回答您的问题,没有简单的方法从vector接管内存,您也许可以使用自定义分配器来解决问题,但我会坚持使用当前的解决方案。 -
叹息 - 库使用错误回调签名的另一个案例。如果回调签名是
void (*callback)(T * data, size_t size, void * user_data)和startProcessing(T* data, size_t size, void * userdata),那么您将有一个简单的解决方案。
标签: c++ c++11 stdvector allocator