使用valuePtr()等为Eigen3 SparseMatrix分配空间

时间:2016-02-26 01:16:14

标签: c++ eigen eigen3

我正在尝试使用Eigen::SparseMatrix A这样的<{p}}来初始化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_dataCompressedStorage类型的受保护变量,其方法value(size_t i)会将引用返回给其内部数据数组的第i个成员。

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

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

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

2 个答案:

答案 0 :(得分:1)

问题很可能是由于您尝试将对象分配给方法!

你的行等于: A.valuePtr() = Sometype_Pointer;A.valuePTR()将调用对象A的Eigen::SparseMatrix::valuePTR方法(函数)。

如果此方法返回指针(T* A::valuePtr()),则返回的指针不是您想要的!该方法将返回 rvalue ; rvalue 不是左值,它不是A中包含的指针,而是指针的临时副本。 您无法直接向其指定任何内容,就像您无法在电视屏幕上触摸人一样。

我正在做一个大量的假设,即你试图做我上面描述的事情,除非那个方法看起来像这样,否则这是不可能的:

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

但是,请注意,对于c ++对象,使用malloc被认为是非常非常过时的,像这一行更像正确     * A.valuePtr()= static_cast(new T [nnz]));

[编辑/]

老实说,我正在努力理解你的代码应该完成什么。大多数人(包括我自己)都不会对这个“特根”课程感到满意。虽然我认为你可能会非常误解它应该如何使用。

您是否可以提供文档链接或您创建/使用此类的示例?

[编辑2 /]

经过一些研究后,我遇到了This article以及This Question,您是否有可能需要使用MappedSparseMatrix

[编辑3 /]

inline Scalar* valuePtr() { return &m_data.value(0); }将返回 rvalue 指针。这不是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.

简而言之,返回的引用不是指向对象(已存在)的指针,而是是对象。这将允许您将对象设置为某个对象,或使用.运算符调用对象上的方法,但是您无法重新分配已存在的内容,因此这是一个错误。

请考虑阅读本文关于rvale和Lvalue在C ++中的区别understanding rvalue and lvalue

答案 1 :(得分:0)

@John Bargman告诉我,我对rvalues和左值的看法是错误的,我想到了并尝试了这个:

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!