我有以下代码:
#include <iostream>
using namespace std;
class test {
public:
test() {
for (int i = 0; i < 5; i++)
this->arr[i] = 0;
}
test(int val) {
for (int i = 0; i < 5; i++)
this->arr[i] = val;
}
test(int* a) {
for (int i = 0; i < 5; i++)
this->arr[i] = a[i];
}
test operator +(test& sub) {
int arr1[5];
for (int i = 0; i < 5; i++) {
arr1[i] = this->arr[i] + sub.arr[i];
}
return test(arr1);
}
void display() {
cout << "The array is: ";
for (int i = 0; i < 5; i++) {
cout << this->arr[i] << "t";
}
}
private:
int arr[5];
};
int main() {
int x = 5;
test obj1(5), obj2(1);
obj2 = obj1 + x; //Error here
obj2.display();
return 0;
}
它试图通过添加两个对象的"arr"成员变量来测试重载"+"运算符,返回一个带有结果的对象并将其分配给主函数中的obj2。然而,根据《绝对C++》一书,也可以像现在这样,通过首先通过"test"类中的构造函数将整数转换为"test"类型,因为该构造函数接受整数类型的变量作为其参数。然后,值为"x"的结果对象将被传递给"+"函数,它将正常工作。
但是,代码无法编译,我尝试此操作时收到错误:没有与这些操作数匹配的"+"运算符。那么,我的代码在解释这本书的细节时可能有什么问题呢?
出现编译错误的原因是operator+
接受非常量左值引用。
如果更改运算符的签名以采用const test&
它将能够绑定到右值,这将进行编译。
test operator +(const test& sub) {
...
}
由于该方法不会修改sub
因此它应该采用 const-ref。
编辑:由于值类别,const
关键字在这里产生了重要差异。首先,让我们看一个简单的例子。
void foo(int& i) {
i = 5;
}
int b;
foo(b); //this is ok
foo(7); //this is not ok
我们指定我们想要一个左值引用。这意味着我们可以传入变量,但不能传入临时变量。在这种情况下,临时是文字,但它也可能是另一个函数的返回值。
如果我们回到你的问题,当你写obj1 + x
时,你已经意识到发生了从int
到test
的转换。该转换的返回值是一个临时值。
如果我们想处理右值(临时(,我们需要使用右值引用。
void foo(int&& i) {
i = 5;
}
int x;
foo(x); // Now this will fail instead
foo(5); // This will however work
当我们使用const&
时,我们是在说我们不会修改该值,并且由于我们已经承诺不修改它,因此它是否是临时的并不重要。无论如何,我们只会从中阅读。
这就是为什么const&
可以绑定到左值或右值的原因。
void foo(const int& i) {
std::cout << i;
}
int x = 7;
foo(x); // This will work
foo(17); // This will also work