在运算符()重载中,'const'关键字有什么作用?

3

我有一个代码库,其中Matrix类的()运算符有以下两个定义:

template <class T> T& Matrix<T>::operator() (unsigned row, unsigned col)
{
    ......
}


template <class T> T Matrix<T>::operator() (unsigned row, unsigned col) const
{
    ......
}

我理解的一件事是第二个声明不返回引用,但是第二个声明中的const是什么意思?另外,当我调用mat(i,j)时,哪个函数被调用?


1
函数上的const修饰符强制编译器检查该函数不会修改类状态或允许更改类状态(传递非常量引用/指针或使用任何非const函数)。 - Pasi Savolainen
3个回答

6

调用哪个函数取决于实例是否为const。第一个版本允许您修改实例:

 Matrix<int> matrix;
 matrix(0, 0) = 10;

如果您有一个Matrix的const实例(引用),则const重载允许只读访问:

 void foo(const Matrix<int>& m)
 {
     int i = m(0, 0);
     //...
     //m(1, 2) = 4; //won't compile
 }

第二个函数不返回引用,因为其意图是禁止修改对象(你得到的是值的副本,因此不能修改矩阵实例)。
在这里,T 应该是一个简单的数值类型,通过值返回会更加便宜。如果 T 也可能是一个更复杂的用户定义类型,那么常量重载也通常会返回一个 const 引用:
 template <class T>
 class MyContainer
 {
      //..,
      T& operator[](size_t);
      const T& operator[](size_t) const;
 }

3

const版本将在const矩阵上调用。在非const矩阵上将调用非const版本。

Matrix<int> M;
int i = M(1,2); // Calls non-const version since M is not const
M(1,2) = 7; // Calls non-const version since M is not const

const Matrix<int> MConst;
int j = MConst(1,2); // Calls const version since MConst is const

MConst(1,2) = 4; // Calls the const version since MConst is const.
                 // Probably shouldn't compile .. but might since return value is 
                 // T not const T.

int get_first( const Matrix<int> & m )
{
   return m(0,0); // Calls the const version as m is const reference
}

int set_first( Matrix<int> & m )
{
  m(0,0) = 1; // Calls the non-const version as m is not const
}

+1,添加一个使用常量引用指向非常量对象的示例也可以有所帮助,因为在大多数情况下,对象本身并不是常量,但函数却会获取/返回指向非常量对象的常量引用。 - David Rodríguez - dribeas
我认为你在第一个和第二个评论中的“first/second”有误(除非楼主更改了定义顺序)。 - Pasi Savolainen
@Pasi - 不确定是怎么发生的。我以为已经仔细检查过了。现在我已经更改了描述,使其能够抵抗在 OP 中重新排序。 - Michael Anderson
@David - 我添加了一个示例来帮助澄清引用问题。 - Michael Anderson

1

调用哪个函数取决于对象是否为const。对于const对象,将调用const重载函数:

const Matrix<...> mat;
const Matrix<...>& matRef = mat;
mat( i, j);//const overload is called;
matRef(i, j); //const overloadis called

Matrix<...> mat2;
mat2(i,j);//non-const is called
Matrix<...>& mat2Ref = mat2;
mat2Ref(i,j);//non-const is called
const Matrix<...>& mat2ConstRef = mat2;
mat2ConstRef(i,j);// const is called

同样适用于指针。如果通过指向常量的指针进行调用,则调用常量重载。否则,调用非常量重载。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接