我正在使用托管C ++模块中的一组非托管C ++ API函数。我从一个API函数中获取double
值(std::vector<std::vector<double>>
)的矩阵,并且需要将矩阵作为double**
参数传递给另一个API函数。我总是可以通过复制元素将原始矩阵重新打包成新的double[][]
。但是,我想避免这种情况,因为使用大型矩阵并且我的方法经常被调用太贵了。
访问原始返回矩阵的元素必须简单,我写了几个简单的模板方法来做到这一点(见下文),但它们不起作用,我有点困惑为什么。我可以从Method1
和Method2
内部访问数组的各个元素,但从任一方法点返回的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;
}
答案 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
不是托管类型。