为什么不使用只读 [] 运算符?
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
则必须如此。您的代码与此有偏差,因此可能会使您的代码的读者感到困惑。
我目前正在用 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
则必须如此。您的代码与此有偏差,因此可能会使您的代码的读者感到困惑。