了解运算符重载的效用

Understanding utility of an operator overloading

本文关键字:重载 运算符 了解      更新时间:2023-10-16

我一直在研究一个旨在创建规则矩阵的类"DenseMatrix"的代码。

浏览代码,有 2 或 3 件事我不太明白。
所以首先这里是这个类的代码:

#include<iostream>
#include<complex>
#include<vector>
#include <cassert>
using namespace std ;
class DenseMatrix{
    typedef complex<double> Cplx;
private:
    int nr, nc;
    vector<Cplx> data;
public :
    DenseMatrix(const int& nr0, const int& nc0){
    nr = nr0; nc = nc0; data.resize(nr*nc,0);}
    DenseMatrix(const DenseMatrix& M){
    nr = M.nr; nc = M.nc; data.resize((M.data).size());
    for (int j=0; j<data.size(); j++) {data[j]=M.data[j];} }
    void operator=(const DenseMatrix& M){
    nr = M.nr ; nc = M.nc ; data.resize((M.data).size());
    for (int j=0; j<data.size() ; j++){data[j]=M.data[j];} }
    Cplx& operator () (const int& j ,const int& k) {
    assert(0<=j && j<nr && 0<=k && k<nc) ; return data[k+j*nc];}
    const Cplx& operator () (const int& j ,const int& k) const {
    assert(0<=j && j<nr && 0<=k && k<nc) ; return data[k+j*nc];}
    friend ostream& operator<<(ostream& o , const DenseMatrix& M){
    for ( int j =0; j<nr ; j++){ for ( int k=0; k<nc; k++){o << M(j,k) << " t " ;} o << endl ;}
    //return o ;}
};

第一件事是,如果我们实际上可以使用复制构造函数并获得相同的结果,那么定义"="运算符的效用是什么?

第二件事,如果我的理解是正确的,Cplx& operator ()将返回一个引用,这个引用实际上将允许我们修改私有属性(matix的一个元素(。但是运算符的第二个定义const Cplx& operator () (const int& j ,const int& k) const是做什么的呢?它的效用是什么?

谢谢!

第一件事是,如果我们实际上可以使用复制构造函数并获得相同的结果,那么定义"="运算符的效用是什么?

因为不能使用复制构造函数来获取相同的结果。复制构造函数是构造函数;当您构造矩阵时会使用它。赋值运算符允许您赋值到已构造的矩阵。

第二件事,如果我的理解是正确的,Cplx&运算符((将返回一个引用,这个引用实际上将允许我们修改[矩阵的一个元素]。

但是运算符的第二个定义const Cplx& operator () (const int& j ,const int& k) const 有什么作用呢?

该版本适用于您有const DenseMatrix的情况。想象一下,你使用了普通的operator() - 你会得到一个可以用来改变矩阵元素的Cplx&。但是,如果矩阵是const矩阵,则不允许更改矩阵元素。编译器不允许在const矩阵上使用第一个版本。

最后一个const(在{之前(说这个函数可以调用const DenseMatrix

第一件事是,如果我们实际上可以使用复制构造函数并获得相同的结果,那么定义"="运算符的效用是什么?

它们是两种不同的野兽。复制构造函数允许您创建一个新对象作为现有对象的副本;赋值运算符允许您将对象复制到现有对象上。所以:

DenseMatrix foo;
...
DenseMatrix bar(foo); // copy constructor
...
foo = bar; // assignment operator

区别是微妙的,但很重要:复制构造函数从一个原始对象开始,而赋值运算符通常也必须摆脱现有数据。

尽管如此,鉴于赋值运算符通常与析构函数 + 复制构造函数非常相似(大多数代码都是重复的(,通常使用 copy & swap 习惯用法来最小化代码重复(同时实现其他有用的属性 - 例如过程中的强异常保证(。


但是运算符的第二个定义const Cplx& operator () (const int& j ,const int& k) const是做什么的呢?它的效用是什么?

const重载是通过类的const实例(或通过const指针或引用访问的"常规"实例(调用的重载;在这种情况下,它们将返回与非const版本相同的数据,但作为const引用而不是纯引用,因此不允许调用方修改矩阵的数据, 根据调用它的对象的恒定性。

引用不允许访问私有属性。这与使用裸对象本身没有什么不同。

一个函数有两个版本的习惯用语,一个const,一个不是,这是很常见的。由于该函数返回引用,因此它从const函数返回const引用。