其中一个最好的解决方案是类似于STLSoft的array_proxy<>模板。不幸的是,由doxygen从源代码生成的文档页面并没有太多帮助理解该模板。实际上,源代码可能会更好:
array_proxy<>
模板在Matthew Wilson的书《Imperfect C++》中描述得很好。我使用的版本是STLSoft网站上的精简版,所以我不需要引入整个库。我的版本不太可移植,但比STLSoft上的版本简单得多(后者跳过了许多可移植性障碍)。
如果您这样设置变量:
int myArray[100];
array_proxy<int> myArrayProx( myArray);
变量myArrayProx有许多STL接口-begin()
,end()
,size()
,迭代器等等。
因此,在许多方面,array_proxy<>
对象的行为就像向量一样(虽然push_back()
不在那里,因为array_proxy<>
无法增长-它不管理数组的内存,只是用更接近向量的东西包裹它)。
array_proxy<>
的一个非常好的特点是,如果将它们用作函数参数类型,则函数可以确定传入的数组的大小,这对于原生数组来说是不正确的。并且包装的数组的大小不是模板类型的一部分,因此使用起来非常灵活。
boost::iterator_range提供类似于容器的接口:
// Memory map an array of doubles:
size_t number_of_doubles_to_map = 100;
double* from_mmap = mmap_n_doubles(number_of_doubles_to_map);
// Wrap that in an iterator_range
typedef boost::iterator_range<double*> MappedDoubles;
MappedDoubles mapped(from_mmap, from_mmap + number_of_doubles_to_map);
// Use the range
MappedDoubles::iterator b = mapped.begin();
MappedDoubles::iterator e = mapped.end();
mapped[0] = 1.1;
double first = mapped(0);
if (mapped.empty()){
std::cout << "empty";
}
else{
std::cout << "We have " << mapped.size() << "elements. Here they are:\n"
<< mapped;
}
不,使用std::vector
是不可能的。
但是如果可能的话,您可以创建具有此大小的向量,并将文件映射到它。
std::vector<double> v(100);
mmapfile_double(&v[0], 100);
关于指向映射区域元素的指针向量(内存消耗较小,因为sizeof(double*) < sizeof(double)),你怎么看?这对你来说可以吗?
有一些缺点(主要是需要特殊的排序谓词),但也有一些好处,例如,您可以删除元素而不更改实际映射内容(或者具有不同元素顺序的偶数个这样的数组,而不对实际值进行任何更改)。
所有使用std::vector在映射文件上的解决方案都存在一个常见问题:将向量内容“固定”到映射区域。这无法跟踪,您只能注意自己不要使用可能导致向量内容重新分配的东西。因此,在任何情况下都要小心。
嗯,向量模板允许提供自己的内存分配器。我自己从未尝试过,但我猜想将其指向您的数组可能并不那么困难,也许可以使用放置 new 运算符...只是猜测,如果我尝试并成功了,我会写更多的。
这是你问题的解决方案。在我想出可行的解决方案之前,我一直在尝试这个问题。注意事项是,在使用后必须将指针清零,以避免重复释放内存。
#include <vector>
#include <iostream>
template <class T>
void wrapArrayInVector( T *sourceArray, size_t arraySize, std::vector<T, std::allocator<T> > &targetVector ) {
typename std::_Vector_base<T, std::allocator<T> >::_Vector_impl *vectorPtr =
(typename std::_Vector_base<T, std::allocator<T> >::_Vector_impl *)((void *) &targetVector);
vectorPtr->_M_start = sourceArray;
vectorPtr->_M_finish = vectorPtr->_M_end_of_storage = vectorPtr->_M_start + arraySize;
}
template <class T>
void releaseVectorWrapper( std::vector<T, std::allocator<T> > &targetVector ) {
typename std::_Vector_base<T, std::allocator<T> >::_Vector_impl *vectorPtr =
(typename std::_Vector_base<T, std::allocator<T> >::_Vector_impl *)((void *) &targetVector);
vectorPtr->_M_start = vectorPtr->_M_finish = vectorPtr->_M_end_of_storage = NULL;
}
int main() {
int tests[6] = { 1, 2, 3, 6, 5, 4 };
std::vector<int> targetVector;
wrapArrayInVector( tests, 6, targetVector);
std::cout << std::hex << &tests[0] << ": " << std::dec
<< tests[1] << " " << tests[3] << " " << tests[5] << std::endl;
std::cout << std::hex << &targetVector[0] << ": " << std::dec
<< targetVector[1] << " " << targetVector[3] << " " << targetVector[5] << std::endl;
releaseVectorWrapper( targetVector );
}
或者你可以创建一个继承自vector的类,在销毁时将指针置空:
template <class T>
class vectorWrapper : public std::vector<T>
{
public:
vectorWrapper() {
this->_M_impl _M_start = this->_M_impl _M_finish = this->_M_impl _M_end_of_storage = NULL;
}
vectorWrapper(T* sourceArray, int arraySize)
{
this->_M_impl _M_start = sourceArray;
this->_M_impl _M_finish = this->_M_impl _M_end_of_storage = sourceArray + arraySize;
}
~vectorWrapper() {
this->_M_impl _M_start = this->_M_impl _M_finish = this->_M_impl _M_end_of_storage = NULL;
}
void wrapArray(T* sourceArray, int arraySize)
{
this->_M_impl _M_start = sourceArray;
this->_M_impl _M_finish = this->_M_impl _M_end_of_storage = sourceArray + arraySize;
}
};