c++ - 只允许修改稀疏矩阵的非零元素

标签 c++ operator-overloading sparse-matrix

我正在实现一个三对角矩阵,我必须尽可能高效。显然我只会保存包含数据的元素。我重载了 operator() 以充当矩阵的索引器,但我希望此运算符返回一个引用,以便用户可以修改矩阵。但是,对于非三对角线元素,我不能只return 0;,因为零不是引用。如何让用户修改三对角线上的数据,但是当 operator() 用于检查非三对角元素时,只返回 0 而不是对 0 的引用?

下面是相关的类定义

template <class T>
class tridiagonal
{
  public:
    tridiagonal();
    ~tridiagonal();
    T& operator()(int i, int j);
    const T& operator()(int i, int j) const; 

  private:
    //holds data of just the diagonals
    T * m_upper;
    T * m_main;
    T * m_lower;
};

最佳答案

您可以使用的一个技巧是让非常量 operator() (int, int) 方法返回一个小的辅助对象。 helper 用于区分分配到矩阵和只提取一个值。这让您对这两个操作有不同的行为。特别是,如果有人试图分配一个必须为零的值,您可以抛出异常。

这段代码至少可以在 VC10 中为我编译,但显然没有链接。

template <class T>
class tridiagonal
{
  public:

    // Helper class that let's us tell when the user is
    // assigning into the matrix and when they are just
    // getting values.
    class helper
    {
        tridiagonal<T> &m_parent;

        int m_i, m_j;

    public:
        helper(tridiagonal<T> &parent, int i, int j)
            : m_parent(parent), m_i(i), m_j(j)
        {}

        // Converts the helper class to the underlying
        // matrix value. This doesn't allow assignment.
        operator const T & () const {
            // Just call the const operator() 
            const tridiagonal<T> &constParent = m_parent;

            return constParent(m_i, m_j);
        }

        // Assign a value into the matrix.
        // This is only called for assignment.
        const T & operator= (const T &newVal) {
            // If we are pointing off the diagonal, throw
            if (abs(m_i - m_j) > 1) {
                throw std::exception("Tried to assign to a const matrix element");
            }

            return m_parent.assign(m_i, m_j, newVal);
        }
    };

    tridiagonal();
    ~tridiagonal();

    helper operator()(int i, int j)
    {
        return helper(*this, i,j);
    }

    const T& operator()(int i, int j) const; 

    private:

    T& assign(int i, int j, const T &newVal);

    //holds data of just the diagonals
    T * m_upper;
    T * m_main;
    T * m_lower;
};

int main(int argc, const char * argv[])
{
    tridiagonal<double> mat;

std::cout << mat(0,0) << std::endl;

const tridiagonal<double> & constMat = mat;

std::cout << mat(2,3) << std::endl;

// Compiles and works
mat(2,3) = 10.0;

// Compiles, but throws at runtime
mat(1, 5) = 20.0;

// Doesn't compile
// constMat(3,3) = 12.0;

    return 0;
}

我已经有一段时间没有这样做了,所以您可能会发现您需要向辅助类添加更多内容,具体取决于您如何使用矩阵。

实际上,这是一个很好的 C++ 练习。 :)

关于c++ - 只允许修改稀疏矩阵的非零元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10081295/

相关文章:

c - CUDA 中的稀疏矩阵加法

r - 在巨大矩阵上应用运算时不允许使用负长度向量

c++ - 为什么优化标志会导致某些模板函数的链接器错误?

c++ - Spirit.X3 使用 string_view 和名为 'insert' 的成员编译错误

c++ - 运算符重载问题

c++ - 为什么 operator[] 只接受一个参数?

c++ - 这是在 Qt 信号和槽中调用带有参数的函数的好方法吗

c++ - 无法将模板参数 this 替换为类型模板参数 _Ty

c++ - C++ 中的赋值与初始化

r - 有效地组合许多文档术语矩阵