C++ c++;给定内存的向量构造

C++ c++;给定内存的向量构造,c++,memory-management,vector,C++,Memory Management,Vector,我想使用std::vector来控制给定的内存块。首先,我很确定这不是一个好的做法,但是好奇心占据了我的上风,我想知道怎么做 我遇到的问题是这样一种方法: vector<float> getRow(unsigned long rowIndex) { float* row = _m->getRow(rowIndex); // row is now a piece of memory (of a known size) that I control vector&l

我想使用std::vector来控制给定的内存块。首先,我很确定这不是一个好的做法,但是好奇心占据了我的上风,我想知道怎么做

我遇到的问题是这样一种方法:

vector<float> getRow(unsigned long rowIndex)
{
    float* row = _m->getRow(rowIndex); // row is now a piece of memory (of a known size) that I control
    vector<float> returnValue(row, row+_m->cols()); // construct a new vec from this data
    delete [] row; // delete the original memory 
    return returnValue; // return the new vector 
}
vector getRow(无符号长行索引)
{
float*row=\u m->getRow(rowIndex);//行现在是我控制的一段内存(大小已知)
vector returnValue(row,row+\m->cols());//从该数据构造一个新的vec
delete[]行;//删除原始内存
returnValue;//返回新向量
}
_m是一个DLL接口类,它返回一个浮点数组,调用方负责删除该数组。所以我想把它包装成一个向量,然后返回给用户。。。。但是这个实现为向量分配新内存,复制它,然后删除返回的内存,然后返回向量

我想做的是直接告诉新的向量,它可以完全控制这个内存块,所以当它被删除时,内存会被清除


更新:最初的动机(从DLL返回的内存)已经被一些响应者相当坚定地压制住了:)然而,无论如何,我很想知道这个问题的答案。。。是否有一种方法可以使用预先分配的内存T*数组的给定块构造std::vector,以及该内存的大小?

您最好的选择可能是
std::vector


更多详细信息请参见。

显而易见的答案是使用自定义分配器,但是您可能会发现,这确实是一个非常重要的解决方案,可以满足您的需要。如果您想这样做,最简单的方法是使用实现定义的分配器(作为默认的scond模板参数to vector),复制该分配器并使其根据需要工作

另一个解决方案可能是定义向量的模板专门化,定义实际需要的尽可能多的接口,并实现内存定制

最后,如何使用一致的STL接口定义您自己的容器,定义随机访问迭代器等等。这可能非常容易,因为底层数组将很好地映射到向量,而指向它的指针将映射到迭代器

关于更新的评论:“有没有一种方法可以使用预先分配的T*数组内存块和该内存的大小来构造std::vector?”


当然,这里的简单答案是“不”。如果您希望结果是一个向量,那么它必须支持按需增长,例如通过reserve()方法,而这对于给定的固定分配是不可能的。所以真正的问题是:你到底想要实现什么?可以像vector这样使用的东西,或者在某种意义上确实必须是vector的东西,如果是,那是什么意思?

vector的默认分配器不提供对其内部的这种访问。您可以使用自己的分配器(vector的第二个模板参数)来完成,但这会改变vector的类型

如果您可以直接在向量中写入,则会容易得多:

vector<float> getRow(unsigned long rowIndex) {
  vector<float> row (_m->cols());
  _m->getRow(rowIndex, &row[0]);  // writes _m->cols() values into &row[0]
  return row;
}
vector getRow(无符号长行索引){
向量行(_m->cols());
_m->getRow(rowIndex,&row[0]);//将_m->cols()值写入&row[0]
返回行;
}

请注意,&row[0]是一个浮点*并且保证vector可以连续存储项。

如果您试图更改vector分配/重新分配/取消分配内存的位置/方式,那么vector类的分配器模板参数就是您要查找的参数

如果您只是试图避免构造、复制构造、赋值和销毁的开销,那么允许用户实例化向量,然后通过引用将其传递给您的函数。然后,用户负责施工和破坏


听起来你要找的是一种智能指针。当它被摧毁时删除它所指向的东西的人。查看Boost库,或者在这种情况下使用自己的库。

这里要知道的最重要的一点是,不同的DLL/模块有不同的堆。这意味着从DLL中分配的任何内存都需要从该DLL中删除(这不仅仅是编译器版本或
delete
vs
delete[]
或其他问题)。不要跨DLL边界传递内存管理职责。这包括在dll中创建并返回
std::vector
。但它还包括将
std::vector
传递给要由DLL填充的DLL;这样的操作是不安全的,因为您无法确定
std::vector
在填充值时不会尝试某种大小调整

有两种选择:

  • std::vector
    类定义自己的
    分配器
    ,该类使用分配函数,该函数保证驻留在创建向量的DLL/模块中。这可以通过动态绑定轻松完成(即,使
    分配器
    类调用一些虚拟函数)。由于动态绑定将在vtable中查找函数调用,因此可以保证它将落在最初创建它的DLL/模块的代码中

  • 不要向DLL传递向量对象或从DLL传递向量对象。例如,您可以使用一个函数
    getRowBegin()
    getRowEnd()
    ,该函数返回行数组中的迭代器(即指针)(如果是连续的),并让用户
    std::将其复制到自己的本地
    std::vector
    对象中。您也可以用另一种方法,将迭代器begin()和end()传递给类似
    fillRowInto(begin,end)
    的函数

这个问题是非常现实的,尽管许多人在不知情的情况下忽视了它。不要低估它。我个人曾遇到过与此问题相关的无声bug,而且它
int main(int argc, char* argv[])
{
  boost::scoped_array<float> array(_m->getRow(atoi(argv[1])));
  return 0;
}