开发者

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

开发者 https://www.devze.com 2023-03-14 10:49 出处:网络
I am working with a set of unmanaged C++ API functions from within a managed C++ module.I obtain a matrix of double values (std::vector<std::vector<double>>) from one API function and need

I am working with a set of unmanaged C++ API functions from within a managed C++ module. I obtain a matrix of double values (std::vector<std::vector<double>>) from one API function and need to pass the matrix as a double** parameter to another API function. I can always repackage the original matrix into a new double[][] by copying elements. However, I want to avoid this, as it gets too expensive with the large matrix and and my method being called frequently.

Accessing the elements of the original returned matrix must be easy, and I wrote a couple of simple template methods to do that (see below), however they are not working and I am a bit puzzled why. I can access individual elements of the array from inside Method1 and Method2, but the T** returned from either of methods points is unusable as it points somewhere else. Could someone help me out, please?

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] = &(vv开发者_StackOverflowT[i][0]);
    }
    T** result = &ptrs[0];
    return result;
}


You are allocating p1 on the stack, as a local variable, and then returning a pointer to it. It will subsequently be wiped out during or after function return as the memory gets reused. Try returning p1 instead and have the function return the pin_ptr, because when the pin_ptr goes out of scope the memory gets unpinned anyway.

A similar scenario would be this:

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


The main problem is that you're passing your vector by value, so the addresses you store no longer point to valid memory as soon as the function returns and said vector goes out of scope. (The same is true of the address you return from Method2, as ptrs goes out of scope.) If you want a double** (as opposed to a const double**), then you need to pass your vector by non-const reference.

The other problem is that you have no way of returning a double** without allocating any memory and consequently forcing someone to delete it later. Your Method2 implemention is almost the correct approach -- rather than deal with the "who's responsibility is it to delete this memory?" issue, it's significantly easier to simply return a std::vector<double*> and when the double** is needed, take the address of the 0th element of that vector instead.

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);

Note that the stored pointers may potentially point to invalid memory as soon as the vector passed to Method3 is modified (i.e., resized or destroyed). Also note that pin_ptr has no place here, as it's for pinning the elements of a managed object and std::vector<> is not a managed type.

0

精彩评论

暂无评论...
验证码 换一张
取 消