访问非托管矢量(C++)中的二维数组

Accessing 2D array in unmanaged vector of vectors (C++)

本文关键字:C++ 二维数组 访问      更新时间:2023-10-16

我正在使用托管C++模块中的一组非托管C++API函数。我从一个API函数获得double值的矩阵(std::vector<std::vector<double>>),并需要将该矩阵作为double**参数传递给另一个API函数。我总是可以通过复制元素将原始矩阵重新打包为新的double[][]。然而,我想避免这种情况,因为由于大矩阵和频繁调用我的方法,它变得过于昂贵。

访问原始返回矩阵的元素一定很容易,我写了几个简单的模板方法来做到这一点(见下文),但它们不起作用,我有点困惑为什么。我可以从Method1Method2内部访问数组的各个元素,但从任何一个方法点返回的T**都不可用,因为它指向其他地方。有人能帮我吗?

T** Method1(vector<vector<T>> vvT)
{
    int size = vvT.size();
    if (size == 0)
        return NULL;
    pin_ptr<T> pin_p1 = &(vvT[0][0]);
    T* p1 = pin_p1;
    T** p2 = &p1;
    return p2;
}
T** Method2(vector<vector<T>> vvT)
{
    int size = vvT.size();
    if (size == 0)
        return NULL;
    vector<T*> ptrs(size);
    for (unsigned i = 0; i < size; ++i)
    {
        ptrs[i] = &(vvT[i][0]);
    }
    T** result = &ptrs[0];
    return result;
}

您在堆栈上分配p1作为一个局部变量,然后返回一个指向它的指针。随着内存的重用,它将在函数返回期间或之后被擦除。请尝试返回p1,并让函数返回pin_ptr,因为当pin_ptr超出范围时,内存无论如何都会被取消固定。

类似的情况是:

int* foo()
{
    int x = 2;
    return &x;
}

主要问题是您通过值传递vector,因此一旦函数返回并且所述vector超出范围,您存储的地址就不再指向有效内存。(从Method2返回的地址也是如此,因为ptrs超出了作用域。)如果您想要double**(而不是const double**),则需要通过非常数引用传递vector

另一个问题是,在不分配任何内存的情况下,您无法返回double**,从而迫使某人稍后再返回delete。您的Method2实现几乎是正确的方法——与其处理"谁对delete这个内存负责?"问题,不如简单地返回std::vector<double*>,当需要double**时,取向量的第0个元素的地址。

template<typename T>
std::vector<T*> Method3(std::vector<std::vector<T> >& vvT)
{
    std::vector<T*> ret;
    for (size_t i = 0, i_max = vvT.size(); i != i_max; ++i)
        ret.push_back(&vvT[i][0]);
    return ret;
}
// ...
std::vector<std::vector<double> > vec = api1();
std::vector<double*> addresses = Method3(vec);
api2(!addresses.empty() ? &addresses[0] : 0);

注意,一旦传递给Method3vector被修改(即,调整大小或破坏),所存储的指针就可能指向无效存储器。还要注意,pin_ptr在这里没有位置,因为它用于固定托管对象的元素,而std::vector<>不是托管类型。