为什么在重载 [] 运算符时无法返回 const 引用



让我们以这段代码为例

#include <iostream>
using namespace std;
struct valStruct {
double& operator[](int i){return values[i];};       //line 6
double operator[](int i) const {return values[i];}; //line 7
double values[4];
};
int main () {
valStruct vals = {0,1,2,3};
cout << "Value before change" << endl;
for ( int i = 0; i < 3; i++ ) {
cout << "vals[" << i << "] = "<< vals[i] << endl;
}
vals[1] = 2.2; // change 2nd element

cout << "Value after change" << endl;
for ( int i = 0; i < 3; i++ ) {
cout << "vals[" << i << "] = "<< vals.values[i] << endl;
}
return 0;
}

我知道第 6 行(请参阅代码中的注释)允许将值写入(和读取!?)到数组values中的索引,而第 7 行仅读取该值。

我理解第 7 行中 const 声明的需要是防止在不打算的情况下更改值(尽管我不明白自第 6 行以来是如何存在的),但我的问题是,为什么我不能将行写为

double& operator[](int i) const {return values[i];}; //line 7

抛出错误:binding reference of type ‘double&’ to ‘const double’ discards qualifiers.

这也提出了一个问题,既然第 6 行存在并且可以同时进行写作和阅读,为什么我们需要第 7 行。

编辑:

我理解 const func() const [此处建议][1] 的想法,我不明白这如何回答我的问题。我不明白回答我问题的两个答案所解释的机制。

我现在明白需要第二行来处理我的函数的 const 对象。

我也明白,当我有一个func()常量时,它隐式地使成员const。这意味着返回的值需要是常量,这就是为什么这不起作用的原因 'double& operator[](int i) const { return values[i]; };´ 虽然这确实 'const double& operator[](int i) const { return values[i]; };´ [1]:为什么在类成员函数中使用关键字"const"两次C++

this引用const限定成员函数中的const对象。这里:

double& operator[](int i) const {return values[i];}; //line 7

您正在尝试返回对this->values[i];的引用。当对象const时,该引用不能是非常量。

通常提供两个重载:

double& operator[](int i) { return values[i]; };              // 1
const double& operator[](int i) const { return values[i]; };  // 2
// ^ returned reference is const 
//                                ^ current object is const

第一个只能在非常量对象上调用。当对象被const时,调用第二个:

valStruct a;
double x = a[0];  // calls 1
const valStruct b;
double x = b[0];  // calls 2

因为复制double并不昂贵,所以您可以返回double而不是引用。

这也提出了为什么我们需要第 7 行

的问题。

因为没有常量operator[]您将无法调用b[].

为什么我们需要第 7 行,因为第 6 行存在并且可以同时进行写作和阅读。

我们需要第 7 行来处理const对象。第 6 行不能用于valStruct类型的const对象。这是因为类对象只能显式调用 const 成员函数const并且第 6 行中的重载operator[]尚未标记为const 成员函数。所以它不能用于类型valStruct的常量对象。因此,我们需要第 7 行,它将重载的operator[]"标记"为 const 成员函数。可以在此处找到有关此内容的更多信息。


现在,如果将第 7 行中的返回类型更改为double&,那么问题是这里您已将operator[]重载为const 成员函数。这意味着数据成员也const。由于我们无法将"对非常量对象的左值引用">绑定到const对象,因此我们得到了上述错误。例如

const double d = 43.4;
double& ref = d;//here we'll get the same error

情况(为什么您会收到错误)类似于上面给出的代码片段。

要解决(摆脱)此错误,我们需要将返回类型从double&更改为const double&

最新更新