【问题标题】:Operator overloading with C++ : class with pointer datat members使用 C++ 重载运算符:具有指针数据成员的类
【发布时间】:2013-11-09 21:41:35
【问题描述】:

我正在尝试使用运算符重载执行基本矩阵运算的程序。下面是我的代码:-

保存矩阵的类

class matrix {
    int r, c;
    int *data;

    public :
    matrix()  //default contstructor
    {
        r=0; c=0;
        data = NULL;
    }

    matrix(int a, int b)   //general matrix constructor.
    {
        r = a; c = b;
        data = new int[sizeof(int) * r * c];;
    }

    //Overloading + operator.
    matrix operator +(matrix & M);

             //Overloading = operator.
    void operator =(matrix & M);
};

然后我创建了一个临时全局对象,如下所示。

matrix temp;

我已经重载了 + 运算符,如下所示。请注意,我必须使用上面创建的全局对象“temp”来保存并返回结果矩阵,因为我的数据成员是 int* 并且我无法返回具有本地范围的对象。

// Addition of matrix
matrix matrix :: operator+(matrix & M)
{
         if(M.r != r || M.c != c) {
           cout<<"Addition is not possible!";
           return temp;
         }
         temp.r = r;
         temp.c = c;
         temp.data = new int(sizeof(int) * r * c);

         for(int i=0; i<r; i++)
         for(int j=0; j<c; j++)
          *(temp.data +(i*c +j)) = *(data +(i*c +j)) + *(M.data +(i*c +j));

     return temp;
}

好的,该程序运行良好...但我的问题是是否有任何有效的替代这个外部“临时”对象?

【问题讨论】:

  • temp 副本极有可能被省略,因此您应该担心的唯一低效问题是当您有诸如 m0 + m1 + m2 + m2 之类的表达式时,其中 mi 都是矩阵。一个常见的解决方案是expression templates,但这很棘手。
  • 除此之外:你的操作符应该是const,并作用于const 引用:matrix operator +(const matrix &amp; M) const;,你的数组的大小看起来很可疑。
  • 为什么要将临时对象声明为全局对象?只需在函数内将其声明为局部变量即可。
  • @JoachimPileborg 所说的。我所说的复制省略假设 temp 是运算符中的局部变量。
  • 将行和列参数作为模板参数是很常见的。例如。 Matrix&lt;4, 4&gt;。这使得将Matrix&lt;4,4&gt; 添加到Matrix&lt;3,3&gt; 成为编译时错误。

标签: c++ oop operator-overloading dynamic-memory-allocation


【解决方案1】:

这个外部“临时”对象有什么有效的替代方法吗?

是的(而且代码中存在一些问题)。

矩阵求和应该通过两种方式实现:

class matrix {
    // ...

    //Overloading + operator.
    matrix& operator +=(const matrix& M); // << notice difference in signature
};

// Addition of matrix
matrix& matrix::operator +=(const matrix& M)
{
     if(M.r != r || M.c != c) {
         cout<<"Addition is not possible!"; // this should throw an exception
                                            // because client code should not have to
                                            // be forced to check the contents of
                                            // std::cout to validate that the operation
                                            // succeeded

         return *this;                      // returning *this
     }

     // this is not necessary
     // temp.r = r;
     // temp.c = c;
     // temp.data = new int(sizeof(int) * r * c);

     for(int i=0; i<r; i++)
         for(int j=0; j<c; j++)
             *(data +(i*c +j)) = *(data +(i*c +j)) + *(M.data +(i*c +j));

     return *this;                          // returning *this
}

这是连接 (+=) 运算符,它很高效,因为它不会创建新的/临时对象。它的问题是它改变了左边的操作数。

第二次实现(和第一次一样高效,并完成上面的代码):

matrix operator +(const matrix& x, const matrix& y) {
    matrix result(x); // you will need a copy constructor
    result += y;      // use operator defined above
    return result;
}

第二个实现使用第一个为矩阵添加加法语义,它不需要是成员。

【讨论】:

  • 请注意,如果您已经编写了operator+=,则不必自己编写operator+,使用Boost.Operators 或我的df.operators 库,第二个允许优化表达式中的一些临时变量喜欢auto result = m1 + m2 + m3 + m4;
  • 我知道,但是 OP 正在研究定义加法运算符的正确签名和语义。在示例中添加 3rd 方库、C++11 允许的优化和/或继承、模板和 CRTP 有点为时过早。我本可以为代码添加更多改进和建议(例如使用 std::vector),但我想专注于正确获取函数签名和(非常基本的)实现。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-08-18
  • 2014-05-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-17
相关资源
最近更新 更多