为什么不使用只读 [] 运算符?

Why isn't the read only [] operator used?

我目前正在用 C++ 编写 Polynomial-class,它应该表示以下形式的多项式:

p(x) = a_0 + a_1*x^1 + a_2*x^2 + ... + a_i*x^i

其中 a_0, ..., a_i 都是 int 的。

class内部使用了一个std::vector<int>类型的成员变量a_来存储常数因子a_0, ..., a_i。要访问常数因子,operator[] 以下列方式重载:

读写:

int &operator[](int i)
{
  return a_.at(i);
}

尝试更改其中一个因素 a_i 时会失败:

i > degree of polynomial = a_.size() - 1

只读:

int operator[](int i) const
{
  if (i > this->degree()) {
    return 0;
  }

  return a_.at(i);
}

略有不同的实现允许相当舒适地循环两个不同大小的多项式的因子(无需担心多项式的度数)。

遗憾的是,我似乎在这里遗漏了一些东西,因为 operator+-重载(利用这个舒适的 read-only-operator[])失败了.

operator+-重载:

Polynomial operator*(const Polynomial &other) {
  Polynomial res(this->degree() + other.degree());

  for (int i = 0; i <= res.degree(); ++i) {
    for (int k = 0; k <= i; ++k) {
      res[i] += (*this)[k] * other[i-k];
    }
  }

  return res;
}

不要介意其中涉及的数学问题。重要的一点是,i 总是在

的范围内
0 <= i < res.a_.size()

因此写入res[i]是有效的。但是 (*this)[k]other[i-k] 尝试读取不一定位于 [0, (*this).a_.size() - 1] 范围内的索引。

我们 只读 operator[] 实现应该没问题吧?我仍然在尝试访问无效索引处的 a_ 时出错。是什么导致编译器在行中使用 读写-实现:

res[i] += (*this)[k] * other[i-k]; 

尤其是等式右边的部分

我确定错误是由 "wrong" 使用 读写 -operator[] 引起的。因为通过额外的检查修复了无效访问:

if (k <= this->degree() && i-k <= other.degree()) {
  res[i] += (*this)[k] * other[i-k];
}

使用 operator[]-重载我错过了什么?为什么这里不使用只读-operator[]

(*this)[k] 正在使用 non-const this 因为包含它的函数不是 const.

因此编译器首选 [] 的 non-const 重载。

您可以使用丑陋的 const_cast 来解决这个问题,但实际上您应该使 [] 运算符的两个版本的行为尽可能相似。此外,[]std::vector 重载并不坚持对索引进行边界检查,而 at 则必须如此。您的代码与此有偏差,因此可能会使您的代码的读者感到困惑。