C++ 修改矩阵后,通过内存指针(memptr)直接访问犰狳矩阵的条目不起作用

C++ 修改矩阵后,通过内存指针(memptr)直接访问犰狳矩阵的条目不起作用,c++,pointers,armadillo,C++,Pointers,Armadillo,我有一个问题,我想通过结构(或类)中的指针访问犰狳矩阵“M”的某些条目。初始化M后,我在结构中设置指针。通过取消对指针的引用,我可以看到它具有正确的值(M-或M(0,0)的第一个条目) 然后我将M改为M*M。但是现在取消对指针的引用不再给我正确的值。奇怪的是:如果我有一个小矩阵,即3x3或4x4(请参阅代码中的“matrixSize”),则不会发生错误。当小矩阵解引用时,指针给出正确的值。 但较大的矩阵会导致错误的值(5x5类似于“2.76282e-320”,这可能是内存中的某个随机位置) 我做

我有一个问题,我想通过结构(或类)中的指针访问犰狳矩阵“M”的某些条目。初始化M后,我在结构中设置指针。通过取消对指针的引用,我可以看到它具有正确的值(M-或M(0,0)的第一个条目)

然后我将M改为M*M。但是现在取消对指针的引用不再给我正确的值。奇怪的是:如果我有一个小矩阵,即3x3或4x4(请参阅代码中的“matrixSize”),则不会发生错误。当小矩阵解引用时,指针给出正确的值。 但较大的矩阵会导致错误的值(5x5类似于“2.76282e-320”,这可能是内存中的某个随机位置)

我做错了什么?我怎样才能解决这个问题

如果有帮助,我想解释一下我想要实现的目标: 我有一个延迟耦合节点网络,每个节点都有某种动态行为。(想想延迟耦合微分方程DDEs-延迟耦合振荡器)。由于它们是延迟耦合的,我需要存储它们过去的状态(它们的历史的数组)。每个振荡器也有一些局部动态,动态变量不影响其他节点,这意味着我不必存储它们的历史。 矩阵用于保存节点某些变量的过去状态。我希望将它们放在矩阵中,因为我希望对它们使用向量运算(矩阵的一个索引表示时间,而另一个是节点索引)。但我还想单独访问它们,以计算每个节点(振荡器)的局部动态。所以我想更新单个节点,但也要更新全局状态。 这就是为什么两种表示都有帮助:对于局部动力学,我通过指向矩阵的指针访问延迟状态。对于全局动力学,我通过矩阵中作为历史数组的行访问耦合变量

#include <iostream>
#include <armadillo>

struct someStruct {
    const double *currentStateInMatrix;
    void printvalue() {std::cout << "*currentState (pointer to first enty of matrix) = " << *currentStateInMatrix << std::endl;}
};

int main(int argc, char* argv[]){

    uint M_size = 4;

    arma::Mat<double> M(M_size, M_size, arma::fill::randu);


    double* pointerIntoMatrix = M.memptr();
    std::cout << "pointer [ " << pointerIntoMatrix << " ] has value: " << *pointerIntoMatrix << std::endl;

    someStruct myStruct;
    myStruct.currentStateInMatrix = pointerIntoMatrix;

    std::cout << "original matrix M: \n" << M;
    myStruct.printvalue();
    std::cout << "\n+++changing contents of matrix M+++\n\n";

    M = M * M;

    std::cout << "M * M: \n" << M;
    myStruct.printvalue();
}
#包括
#包括
结构someStruct{
常数双*当前状态矩阵;

void printvalue(){std::cout犰狳中的操作
M=M*M
是矩阵乘法(不是元素对元素的乘法)。因此,将
M*M
的中间计算直接存储到
M
中会有问题。它会覆盖
M
中的现有数据,而完成
M*M
操作仍然需要这些数据

假设犰狳检测到这个问题并将
M*M
的结果存储到单独的内存块中,然后将该块分配给
M
,这可能是安全的

有很多方法可以解决这个问题。使用固定大小的矩阵,如注释中提到的darcamo。使用
Mat::fixed M;
来声明矩阵

另一种方法是手动管理矩阵元素的内存,并告诉
M
矩阵始终使用该内存

mat(ptr_aux_mem, n_rows, n_cols, copy_aux_mem = true, strict = false)
因此,我们可以:

double* my_mem = (double*)std::malloc(M_size * M_size * sizeof(double));
// or use new[]

Mat<double> M(my_mem, M_size, M_size, false, true);

// don't forget to call std::free(my_mem) or delete[] when done!
double*my_mem=(double*)std::malloc(M_size*M_size*sizeof(double));
//或者使用新的[]
Mat M(我的记忆、大小、大小、假、真);
//完成后不要忘记调用std::free(my_mem)或delete[]!

需要注意的是,上述两种解决方法(固定大小矩阵和手动内存管理)可能会有轻微的性能损失。无法避免为
M=M*M
操作使用单独的内存块。使用这些解决方法时,犰狳会将
M*M
的结果存储到临时缓冲区中,然后将缓冲区的内容复制到
M
MyMatrix使用的内存中x=myMatrix*myMatrix
可能会导致
arma::Mat
实例内部重新分配。因此,您保存的指针值不再有效。是否有办法防止这种情况发生?
M*M
创建一个新的临时对象,然后将其分配给
M
。因此,以前的指针不再有效。对于此case您可以用
M*=M
替换
M=M*M
,它也可以工作,但即使这样,我也不确定它是否能得到保证。但是,如果您使用
Mat::fixed
而不是
Mat::fixed
,则在编译时为
M
分配内存,并且
M*=M
保证不会使指针无效并保存指针结果在相同的内存中。哦,谢谢!看来我必须进入犰狳的腹部深处。这里有很多诡计。但这真的很有帮助!我将尝试一些高级构造函数方法。另外:我刚刚有了另一个关于M为什么改变其位置(从而使指针无效)的想法:如果M不是平方,则操作M*M返回一个不同大小的矩阵。在最佳情况下,返回的矩阵较小(并且可以装入相同的内存-具有不同的边界)。在最坏情况下,返回的矩阵较大。M是平方是大小保持不变的一种情况。