使用 valuePtr() 等为 Eigen3 SparseMatrix 分配 space

Using valuePtr() etc to allocate space for Eigen3 SparseMatrix

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

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。

编辑: classSparseMatrix的函数valuePtr

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

Scalar 是模板参数。 m_data 是类型 CompressedStorage 的受保护变量,其方法 value(size_t i) returns 对其内部数据数组的第 i 个成员的 引用

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

所以,我得出的结论是valuePtr()returns数组首元素的地址。那么,我应该能够通过 malloc 为该数组分配 space。

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

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

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

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

我假设您正在尝试执行我上面描述的操作,除非该方法看起来像这样,否则这是不可能的:

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

但是,请注意使用 malloc 对于 c++ 对象来说被认为是非常非常过时的,类似这行的东西会更 正确 *A.valuePtr() = static_cast(新 T[nnz]));

[编辑/]

老实说,我非常努力地了解您的代码应该完成什么。大多数人(包括我自己)都不会熟悉这个 "Eigen" class。虽然我认为您可能非常误解它应该如何使用。

您能否提供一个 link 文档,或者您如何创建/使用此 class 的示例?

[编辑 2/]

经过一番研究,我发现了 This article as well as This Question, could it be possible you need to use a MappedSparseMatrix

[编辑 3/]

inline Scalar* valuePtr() { return &m_data.value(0); } 将 return 一个 rvalue 指针。这不是 m_data 中保存的对象,也不是内部使用的指针。它是指向现有对象的指针的临时副本,试图说"make this temporary copy point to something else"没有意义。

inline Scalar& value(size_t i) { return m_values[i]; } 在这种情况下,方法 return 是对对象 的引用 ,引用不是指针 - (尽管 & 经常让人感到困惑)。
一个引用可以理解为原始对象,不需要解引用一个引用。考虑以下因素。

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.

简而言之,被return编辑的引用不是指向对象(已经存在)的指针,而是对象。这将允许您将对象设置为某物,或使用 . 运算符调用对象上的方法,但是您不能重新分配已经存在的东西,因此是错误的。

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

在@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] = '[=10=]';

    // 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() 一样,return 是某种地址类型的文字;它不是 return 左值。尝试将某些内容(在本例中,内存块的起始地址 return 由 malloc 编辑)分配给文字(在本例中,某些地址,如 0x233ff554)是没有意义的。我想我现在明白它是如何工作的了。谢谢@John Bargman!