c++ - 在函数超出范围后保留特征矩阵不被删除
问题描述
我Eigen::MatrixXf m
存储了一些数据,我需要在另一个数组中使用这些数据vtkFloatArray
。为了避免复制我做的数据:
vtkNew<vtkFloatArray> array; // `vtkNew` is a smart pointer class
{
Eigen::MatrixXf m(2, 2);
m << 1, 2, 3, 4;
array->SetArray(m.data(), m.size(), 1);
}
// `array` must go on living and have access to the `.data()` pointer
问题是array
必须比特征矩阵的寿命长得多,m
但是当执行超出范围时,似乎array
无法获取值,因为它们被删除(m
超出范围时特征矩阵被删除)。
看来我可以动态分配特征矩阵:
vtkNew<vtkFloatArray> array;
{
Eigen::MatrixXf* m = new Eigen::MatrixXf(2, 2);
m << 1, 2, 3, 4;
array->SetArray(m->data(), m->size(), 1);
}
// `array` must go on living and have access to the `.data()` pointer
然而SetArray()有一些选项来保存和删除数组我怀疑如果我使用这种方法我会得到内存泄漏。可能std::shared_ptr<Eigen::MatrixXf> m
可以帮助我,但我不确定它应该计算矩阵上的引用和m
指针的引用(尽管我可能弄错了),而且我也会出现内存泄漏。vtkFloatArray
m.data()
如果有人知道如何在活着的时候让我的特征矩阵保持vtkFloatArray
活跃并且不会发生内存泄漏,请解释一下。
问候
解决方案
我的解决方案基于@Peter-ReinstateMonica 的建议:创建一个包装类,其中两个对象vtkFloatArray
都Eigen::MatrixXf
将驻留,这将使控制这两个对象的生命周期成为可能。
让我们调用包装类vtkEigenFloatArray
并让它继承自vtkFloatArray
. 由于我们的包装类隐式继承,我们应该遵循vtkvtkObject
的继承结构,使其在 vtk 中可用(例如)。vtkNew<vtkEigenFloatArray>
vtkFloatArray
我们将Eigen::MatrixXf* eigArr
成员变量添加到我们的vtkEigenFloatArray
类中。
我们还添加了Eigen::MatrixXf* GetEigenArray()
返回Eigen::MatrixXf* eigArr
指针和设置器的方法,void SetEigenArray(Eigen::MatrixXf* arr)
以便可以使用Eigen::MatrixXf
外部创建的类的内部对象。
值得注意的是,它vtkEigenFloatArray
和它的受保护Eigen::MatrixXf* eigArr
对象共享同一个缓冲区。每次调用void UpdateEigenBuffer()
函数时设置。此外,每次Eigen::MatrixXf* eigArr
从创建的类外部调整大小时,都void UpdateEigenBuffer()
必须调用该函数来更新vtkFloatArray
继承类的大小。
此外,用户绝不能从外部删除 Eigen::MatrixXf* eigArr
,因为它在vtkEigenFloatArray
's 的析构函数中被删除。
建议解决方案的缺点:
当主vtkEigenFloatArray
对象被删除时,指针Eigen::MatrixXf* eigArr
将不等于nullptr
。Eigen::MatrixXf* eigArr
因此,当您没有持有人vtkEigenFloatArray
对象时,您无法检查是否还活着。
#include <vtkNew.h>
#include <vtkFloatArray.h>
#include <Eigen/Dense>
#include <iostream>
class vtkEigenFloatArray : public vtkFloatArray
{
public:
static vtkEigenFloatArray* New();
vtkTypeMacro(vtkEigenFloatArray, vtkFloatArray);
void PrintSelf(ostream& os, vtkIndent indent) override
{
this->RealSuperclass::PrintSelf(os, indent);
}
// This macro expands to the set of method declarations that
// make up the interface of vtkAOSDataArrayTemplate, which is ignored
// by the wrappers.
#if defined(__VTK_WRAP__) || defined(__WRAP_GCCXML__)
vtkCreateWrappedArrayInterface(float);
#endif
/**
* A faster alternative to SafeDownCast for downcasting vtkAbstractArrays.
*/
static vtkEigenFloatArray* FastDownCast(vtkAbstractArray* source)
{
return static_cast<vtkEigenFloatArray*>(Superclass::FastDownCast(source));
}
/**
* Get the minimum data value in its native type.
*/
static float GetDataTypeValueMin() { return VTK_FLOAT_MIN; }
/**
* Get the maximum data value in its native type.
*/
static float GetDataTypeValueMax() { return VTK_FLOAT_MAX; }
/**
* Deletes previous pointer and sets new
*/
void SetEigenArray(Eigen::MatrixXf* arr)
{
delete eigArr;
eigArr = arr;
UpdateEigenBuffer();
}
/**
* Don't delete this pointer!
*/
Eigen::MatrixXf* GetEigenArray()
{
return eigArr;
}
/**
* Must be manually called every time Eigen::MatrixXf resized
*/
void UpdateEigenBuffer()
{
this->SetArray(eigArr->data(), eigArr->size(), 1); // must be set to 1 or in destructor runtime error
}
protected:
vtkEigenFloatArray()
{
eigArr = new Eigen::MatrixXf();
}
~vtkEigenFloatArray() override
{
delete eigArr;
eigArr = nullptr;
}
Eigen::MatrixXf* eigArr;
private:
typedef vtkAOSDataArrayTemplate<float> RealSuperclass;
vtkEigenFloatArray(const vtkEigenFloatArray&) = delete;
void operator=(const vtkEigenFloatArray&) = delete;
friend class vtkNew<vtkEigenFloatArray>;
};
vtkStandardNewMacro(vtkEigenFloatArray);
int main(int argc, char *argv[]) {
/* General usage */
vtkNew<vtkEigenFloatArray> arr;
Eigen::MatrixXf* M = arr->GetEigenArray();
M->resize(2, 2);
*M << 1, 2, 3, 4;
arr->UpdateEigenBuffer();
std::cout << "Eigen M:" << std::endl;
std::cout << *M << std::endl;
std::cout << "VTK array:" << std::endl;
for(int i = 0; i < arr->GetSize(); i++)
std::cout << arr->GetValue(i) << std::endl;
arr->Allocate(5);
std::cout << "Eigen M:" << std::endl;
std::cout << *M << std::endl;
std::cout << "VTK array:" << std::endl;
for(int i = 0; i < arr->GetSize(); i++)
std::cout << arr->GetValue(i) << std::endl;
/* Test `SetEigenArray` */
Eigen::MatrixXf* MM = new Eigen::MatrixXf();
MM->resize(2,2);
*MM << 11, 22, 33, 44;
arr->SetEigenArray(MM);
std::cout << "Eigen MM:" << std::endl;
std::cout << *MM << std::endl;
std::cout << "VTK array:" << std::endl;
for(int i = 0; i < arr->GetSize(); i++)
std::cout << arr->GetValue(i) << std::endl;
return 0;
}
推荐阅读
- django - Methode() 为参数 'name' 获得了多个值
- python - 如何将高斯过程回归应用于系列问题?
- c - 返回和释放链表节点
- javascript - 此路由不支持 POST 方法。支持的方法:GET、HEAD。尝试使用ajax向控制器发送数据
- c++ - GDI+ 视口优化
- php - 字符串到 PHP 中的 \xHH
- laravel - Vue 扩展 vue2-google-maps 的 Vue 导入给出错误
- docker - 将两个 API 与 RabbitMQ 和 Docker 连接的最佳方式是什么?
- python - 将scrapy导出到csv
- r - 按多列排序不起作用 - R Dataframe