C++ 将动态数组包装到STL/Boost容器中?

C++ 将动态数组包装到STL/Boost容器中?,c++,arrays,boost,vector,containers,C++,Arrays,Boost,Vector,Containers,我需要将一个动态分配的数组(例如,从a=new double[100])包装到std::vector(最好)中,而不复制数组。 这个限制是因为我要包装的数组是从文件中复制的,所以只需执行vector(a,a+size)将使内存使用量增加一倍 有什么技巧可以做到这一点吗?没有,这是不可能使用std::vector的 但是如果可能的话,你可以创建这个大小的向量,并可能将文件映射到这个大小 std::vector<double> v(100); mmapfile_double(&v

我需要将一个动态分配的数组(例如,从a=new double[100])包装到std::vector(最好)中,而不复制数组。 这个限制是因为我要包装的数组是从文件中复制的,所以只需执行vector(a,a+size)将使内存使用量增加一倍


有什么技巧可以做到这一点吗?

没有,这是不可能使用
std::vector

但是如果可能的话,你可以创建这个大小的向量,并可能将文件映射到这个大小

std::vector<double> v(100);
mmapfile_double(&v[0], 100);
标准:向量v(100); mmapfile_-double(&v[0],100);
指向映射区域元素的指针向量如何(减少了sizeof(double*) 有一些缺点(主要是需要特殊的谓词进行排序),但也有一些好处,例如,可以在不更改实际映射内容的情况下删除元素(或者在不更改实际值的情况下,使用不同元素顺序的偶数个这样的数组)


使用映射文件上的std::vector的所有解决方案都有一个共同的问题:将向量内容“钉”到映射区域。这是无法跟踪的,您只能自己观察,不要使用可能导致矢量内容重新分配的内容。所以无论如何都要小心。

我曾经下定决心要完成同样的事情。经过几天的思考和尝试,我觉得这不值得。我最终创建了自己的定制向量,其行为类似于std::vector,但只具有我实际需要的功能,如绑定检查、迭代器等


如果您仍然希望使用std::vector,那么我当时能想到的唯一方法就是创建一个自定义分配器。我从来没有写过一个,但鉴于这是控制STL内存管理的唯一方法,也许可以在那里做一些事情。

最好的解决方案之一是类似模板的东西。不幸的是,doxygen从源代码生成的文档页面对理解模板并没有很大帮助。源代码实际上可能更好一些:

中很好地描述了
array\u proxy
模板。我使用的版本是STLSoft站点上的精简版本,因此我不必拉入整个库。我的版本没有那么便携,但这使得它比STLSoft上的版本简单得多(STLSoft跨越了很多便携性的障碍)

如果您这样设置变量:

int myArray[100];

array_proxy<int> myArrayProx( myArray);
int-myArray[100];
数组\代理myArrayProx(myArray);
变量
myArrayProx
具有许多STL接口-
begin()
end()
size()
、迭代器等

因此,在许多方面,
array\u proxy
对象的行为就像一个向量(尽管
push\u back()
不存在,因为
array\u proxy
无法增长-它不管理数组的内存,它只是将它包装在一个稍微接近向量的东西中)


使用
array\u proxy
的一个非常好的地方是,如果您将它们用作函数参数类型,函数可以确定传入的数组的大小,这对于本机数组是不正确的。而且包装数组的大小不是模板类型的一部分,因此使用起来非常灵活。

您可以使用array\u proxy,或者查看一下。它为您提供size()、front()、back()、at()、operator[]等。就个人而言,我更喜欢Boost.Array,因为Boost更为流行。

A提供了一个类似容器的界面:

// 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;
}
//内存映射一个双精度数组:
大小\u t数量\u加倍\u至\u映射=100;
double*from_mmap=mmap_n_double(从_double到_map的数量);
//将其包装在迭代器范围内
typedef boost::迭代器_范围映射双精度;
映射双倍贴图(从_mmap,从_mmap+从_double到_map的数量);
//使用范围
MappedDoubles::迭代器b=mapped.begin();
MappedDoubles::迭代器e=mapped.end();
映射的[0]=1.1;
双优先=映射(0);
if(mapped.empty()){

std::cout嗯,向量模板允许提供您自己的内存分配器。我自己从来没有这样做过,但我想让它指向您的数组并不是那么困难,可能是使用了新的运算符…只是一个猜测,如果我尝试并成功,我会写更多的内容。

这是您问题的解决方案。我一直在断续续地尝试在我想出一个可行的解决方案之前,已经有一段时间了。需要注意的是,在使用指针之后,必须将指针归零,以避免双重释放内存

#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 );
}
#包括
#包括
模板
void wrapArrayInVector(T*sourceArray,size\u T arraySize,std::vector和targetVector){
typename std::_Vector_base::_Vector_impl*vectorPtr=
(typename std::_Vector_base::_Vector_impl*)((void*)和targetVector);
vectorPtr->_M_start=sourceArray;
vectorPtr->\u M\u finish=vectorPtr->\u end\u of_storage=vectorPtr->\u M\u start+arraySize;
}
模板
无效释放向量包装器(std::vector和targetVector){
typename std::_Vector_base::_Vector_impl*vectorPtr=
(typename std::_Vector_base::_Vector_impl*)((void*)和targetVector);
vectorPtr->\u M_start=vectorPtr->\u M_finish=vectorPtr->\u M_end\u of_storage=NULL;
}
int main(){
int测试[6]={1,2,3,6,5,4};
std::vector targetVector;
wrapArrayInVector(测试,6,目标向量);

std::cout+1似乎是最好的解决方案,特别是因为代理不应该重新分配内存,所以它应该没有很多问题。我建议不要编写自己的容器。这在大多数情况下根本不值得,并且会导致很多互操作性问题。此外,花在调试重新发明的东西上的时间是浪费时间的。客户不过,om分配器可能很容易实现,而且是一种更好的方法。通常我会同意,但我真的认为这取决于您将如何使用它。std::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;
  }   
};