代码之家  ›  专栏  ›  技术社区  ›  Aditya Kashi

使用valuePtr()等为特征3稀疏矩阵分配空间

  •  1
  • Aditya Kashi  · 技术社区  · 8 年前

    我正在尝试初始化 Eigen::SparseMatrix A 通过使用 malloc 这样地

    A.valuePtr() = static_cast<T*>(std::malloc(nnz*sizeof(T)));
    A.innerIndexPtr() = static_cast<int*>(std::malloc(nnz*sizeof(int)));
    

    但我弄错了

    error: lvalue required as left operand of assignment
    

    对于这两种说法。如果重要的话,包含行的函数需要 Eigen::SparseMatrix<T, Eigen::RowMajor> 通过引用。

    有人能帮我吗?我使用的是g++5.2。

    编辑: 功能 valuePtr 类别的 SparseMatrix

    inline Scalar* valuePtr() { return &m_data.value(0); }
    

    Scalar 是模板参数。 m_data 是类型为的受保护变量 CompressedStorage 谁的方法 value(size_t i) 返回一个 参考 到其内部数据数组的第i个成员。

     inline Scalar& value(size_t i) { return m_values[i]; }
    

    所以,我得出结论 valuePtr() 返回数组的第一个元素的地址。那么,我应该能够通过malloc为该数组分配空间。

    如果有人感兴趣,我会提供一个参考链接——请参见84和131之后的行。 Eigen3 SparseMatrix class

    2 回复  |  直到 8 年前
        1
  •  1
  •   Community Aniket Inge    7 年前

    问题很可能是因为您试图将对象分配给方法!

    您的行等于: A.valuePtr() = Sometype_Pointer; , A.valuePTR() 将致电 Eigen::SparseMatrix::valuePTR 对象A的方法(函数)。

    如果此方法返回指针( T* A::valuePtr() )那么返回的指针不是您想要的!该方法将返回 右值 ; 一 右值 不是 左值 这不是A中包含的指针,而是 临时副本 指针的。
    你不能直接给它分配任何东西,就像你不能触摸电视屏幕上的人一样。

    我做了一个很大的假设,你想做我上面描述的事情,除非这个方法看起来像这样,否则这是不可能的:

    T ** Eigen::SparseMatrix::valuePTR()
    {
        return &T;
    }
    *A.valuePtr() = static_cast<T*>(std::malloc(nnz*sizeof(T)));
    

    然而,请注意,对于c++对象来说,使用malloc被认为是非常过时的,类似于这一行的内容会更 对的 *A。valuePtr()=static_cast(新T[nnz]));

    [编辑/]

    老实说,我正在非常努力地理解你的代码应该完成什么。大多数人(包括我自己)都不会熟悉这个“Eigen”课程。尽管我认为你可能会误解它应该如何使用。

    你能提供一个文档的链接,或者一个如何创建/使用这个类的例子吗?

    [编辑2/]

    经过一番研究,我发现 This article 以及 This Question ,您是否需要使用 MappedSparseMatrix

    [编辑3/]

    inline Scalar* valuePtr() { return &m_data.value(0); } 将返回 右值 指针。这不是m_data中保存的对象,也不是内部使用的指针。这是暂时的 指向现有对象的指针的副本 ,试图说“让这个临时副本指向其他东西”是没有意义的。

    inline Scalar& value(size_t i) { return m_values[i]; } 在这种情况下,该方法返回 对对象的引用 ,引用不是指针-(尽管 & 经常混淆人们)。
    参考可以理解为 原始对象 ,你不需要 取消引用 参考。考虑以下内容。

    int A;
    int * A_p = &A;
    int & A_r = A;
    int & A_r_2 = *A_p;
    
    //de-reference the pointer (to create a reference)
    *A_p = 10;  //A == 10
    //Assign directly to A (via the reference)
    A_r = 12; // A == 12
    //assign directy to A (via the reference to A, that was taken from A_p
    A_r_2 = 15; // A == 15
    //attempt to de-reference a reference
    *A_r = 10; //ERROR, A_r is not a pointer.
    

    简而言之,返回的引用不是指向对象(已经存在)的指针,而是 是对象 。这将允许您将对象设置为某个对象,或使用 . 但是,您不能重新分配已经存在的内容,这是一个错误。

    请考虑阅读这篇关于C语言中右值和左值的区别的文章++ understanding rvalue and lvalue

        2
  •  0
  •   Aditya Kashi    8 年前

    在@John Bargman告诉我我对右值和左值的看法是错误的之后,我想了想,试了一下:

    class A
    {
        char* str;
    public:
    
        // This function returns a literal (constant) of type char* 
        // (just an address), not a pointer variable
        char* getstr() {
            return str;
        }
    
        char getchar(const int i) const {
            return str[i];
        }
    };
    
    int main()
    {
        A a;
    
        // the RHS can't be assigned to a literal, we need a variable in the LHS
        a.getstr() = static_cast<char*>(malloc(10*sizeof(char)));   // ILLEGAL!
    
        // this assigns the address contained in str to mstr.
        char* mstr = a.getstr();
    
        // after this, mstr will have nothing to do with A::str; the former 
        // will have been re-assigned to a different address
        mstr = static_cast<char*>(malloc(10*sizeof(char)));
    
        for(int i = 0; i < 9; i++)
            mstr[i] = '0';
        mstr[9] = '\0';
    
        // The following line segfaults as no storage has been allocated to A::str
        cout << a.getchar(1) << endl;   // runtime error!
    
        free(mstr);
        return 0;
    }
    

    现在我明白了 SparseMatrix::valuePtr() 喜欢 A::getstr() ,返回某个地址类型的文本;它不返回左值。尝试分配一些东西(在本例中,返回的内存块的起始地址 malloc )对于文字(在本例中,某些地址如0x233ff554)是没有意义的。我想我现在明白了它的工作原理。谢谢@John Bargman!