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

时间:2011-06-21 00:39:33

标签: .net c++ arrays

我正在使用托管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;
}

2 个答案:

答案 0 :(得分:0)

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

类似的情况是:

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

答案 1 :(得分:0)

主要问题是您通过值传递vector,因此一旦函数返回并且vector超出范围,您存储的地址就不再指向有效内存。 (对于您从Method2返回的地址也是如此,因为ptrs超出了范围。)如果您想要double**(而不是const double**),那么你需要通过非const引用传递你的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);

请注意,一旦传递给vector的{​​{1}}被修改(即调整大小或销毁),存储的指针可能会指向无效的内存。另请注意,此处Method3没有位置,因为它用于固定托管对象的元素,而pin_ptr不是托管类型。