【问题标题】:A custom Vector and Matrix class in C++ and operator[]C++ 和 operator[] 中的自定义向量和矩阵类
【发布时间】:2011-08-24 16:16:37
【问题描述】:

我在 C++ 中有一个向量类,它依赖于原始指针。我不使用 std::vector 因为我需要为特殊情况从原始指针创建向量对象。这是我的课程非常简单的示例:

template <typename T>
class Vector
{ ...
  private:
    T * m_data; int m_size; bool dontFree; ...
  public:
    Vector(T *const ptr, int size) { m_data = ptr; m_size = size; dontFree = true; }
    Vector(int size, T val) {  ...  dontFree = false; }
    ~Vector(): {   if(!dontFree) delete [] m_data; }
    T& operator[](const size_type index);
};

同样,我有矩阵数据类型,它也将数据存储在原始指针中,并且可以使用向量来支持 [][],因为它在 C++ 中是不允许的,例如:

template<typename T>
class Matrix
{
  private:
   T * m_data; ...

 public:
  ... 
  Vector<T>& operator[](const int rowIndex)
  {
     return Vector<T>(&m_data[rowSize * rowIndex], rowSize);
  }
}

我怎样才能有效地实现 operator[] 矩阵返回向量,以便我可以编写代码,如下所示:

Matrix<int> m(5,5);
m[1][1] = 10;
int temp = m[1][2];

请建议考虑复制构造函数等的开销。

【问题讨论】:

  • 通过拷贝返回向量,而不是通过引用返回,无效。复制成本很低,甚至可以完全优化。
  • 你能更好地解释为什么你不能使用std::vector吗?内存范围 [m_data, m_data + size] 是否已经分配?可能一个 c++1x 移动构造函数可以解决您的问题。
  • @Wiso:我认为这里的想法是创建矩阵的“切片视图”,它允许您将行和列视为一维向量。使用辅助类来做这件事很好,而且应该很高效,因为您不需要移动任何实际数据。

标签: c++ stl vector


【解决方案1】:

创建一个重载 operator[] 的代理类,您可以授予对矩阵数组的访问权限。像这样的:

template<typename T>
class Proxy
{
public:
    Proxy(T * tp)
        :rowStart(tp)
    {}

    T & operator[](const int columnIndex)
    {
        return rowStart[columnIndex];
    }

private:
    T * rowStart;
};

然后您的 Matrix 类的 operator[] 可以返回其中之一,如下所示:

Proxy<T> operator[](const int rowIndex)
{
     return Proxy<T>(m_data + rowSize * rowIndex);
}

这当然不完整,但它应该可以帮助您入门。

【讨论】:

  • 谢谢,但您能解释一下为什么使用 Vector 类而不是 Proxy 不好吗?
  • 你原来的Vector&lt;T&gt;充当作为代理,所以是类似的。出于其他原因,我会尽量避免它(好吧,实际上是Vector&lt;T&gt; 和任何其他代理)。特别是重用Vector&lt;T&gt; 有时管理资源,有时可能不会成为未来问题的根源(即类不变量因使用类的位置而异,这意味着它们不是真正的不变量)
【解决方案2】:

您应该按值返回向量以使您的代码正确。如果你的向量在复制构造函数中做了很多工作,你也可以编写一个小代理。

如果您将 operator[] 实现为内联方法(例如,不要将实现移至 cpp),那么好的编译器应该优化您的代码并消除不必要的复制。

但是如果你对性能很着迷,那么你可以从操作符返回一个原始指针:

... 
T* operator[](const int rowIndex)
{
  return m_data + rowSize * rowIndex;
}
...
int temp = m[1][2];

但这是一种危险的方法!

【讨论】:

    【解决方案3】:

    在实现多维矩阵时,建议不要重载operator[],而是使用多维重载operator()。有几个原因你可以阅读C++ FAQ lite

    template <typename T>
    class Matrix {
    public:
       typedef std::size_t size_type;
       typedef T & reference;
       typedef T const & const_reference;
    
       const_reference operator()( size_type x, size_type y ) const;
       reference operator()( size_type x, size_type y );
    };
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-08-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-24
      • 1970-01-01
      相关资源
      最近更新 更多