C++ 运算符的返回值++;
我有下面的代码被破坏了。我可以通过修改代码中的某一行来修复它(参见注释)。问题的原因是什么C++ 运算符的返回值++;,c++,C++,我有下面的代码被破坏了。我可以通过修改代码中的某一行来修复它(参见注释)。问题的原因是什么 #include <iostream> using namespace std; class Number{ public: int n; Number(int a):n(a){} //when I change the following to //friend Number& operator++(Number& source, int
#include <iostream>
using namespace std;
class Number{
public:
int n;
Number(int a):n(a){}
//when I change the following to
//friend Number& operator++(Number& source, int i)
//then it compiles fine and correct value is printed
friend Number operator++(Number& source, int i){
++source.n;
return source;
}
};
int main() {
Number x(5);
x++++; //error: no 'operator++(int)' declared for postfix '++' [-fpermissive]
cout<<x.n;
return 0;
}
#包括
使用名称空间std;
班号{
公众:
int n;
数字(inta):n(a){
//当我将以下内容更改为
//朋友编号和运算符++(编号和来源,int i)
//然后,它编译出精细的值,并打印出正确的值
朋友编号运算符++(编号和源,int i){
++资料来源:n;
返回源;
}
};
int main(){
数字x(5);
x++++;//错误:没有为后缀“++”[-fpermissive]声明“运算符++(int)”
cout您正在通过写入x++
来增加内部运算符+++
的返回值。这意味着如果该运算符的返回值不可修改,则代码将无法编译
因此,如果将其声明为返回Number
而不是Number&
,则不能对其进行修改(函数的返回值是临时值,而不是左值,除非它是引用,因此外部运算符+++通过(非常量)引用获取它,不能将其绑定到通过值返回的对象).尝试将第二个++
应用于第一次调用返回的临时对象。但是,操作数必须通过引用传递,并且不能将临时对象绑定到非常量左值引用
您可能不想“修复”这个问题,因为几乎没有理由修改这样的临时值。但是,您应该在递增之前返回该值的副本,以提供预期的递增后行为
前缀运算符应该返回一个引用,该引用可以很好地绑定到另一个引用,以便++++x;
能够按预期工作。您尝试执行的操作非常不寻常。增量后通常返回一个表示增量前对象的右值(与pre-increment相反,pre-increment首先递增对象,然后返回对象本身,作为左值)。出于无法解释的原因,您基本上是在尝试使post-increment的行为与pre-increment相同
通常,您会这样做:
class Number {
int n;
public:
// Pre-increment
Number& operator++() {
++n;
return *this;
}
Number operator++(int) {
Number temp = *this; // capture old value
++(*this);
return temp;
}
};
根据这个定义,x++
不会编译,但是当x
是int
时,它也不会编译:这没有多大意义
无论如何,它不适合您的原因如下。x++
被解释为
operator++(operator++(x, 0), 0)
内部的operator++
调用返回一个临时的Number
对象。外部的operator++()
需要一个类型为Number&
的参数,但非常量引用不能绑定到临时引用。当您更改声明,使操作符+
返回Number&
-一个左值时,可以将此返回值愉快地传递给外部操作符+
调用。让我们从观察你也不能像这样为int
链接postincrement操作符
在我解决这个问题之前,让我建议不要写这样不直观的代码。从现在起一年后,有人将不得不阅读你的程序,你想让它尽可能容易地阅读
考虑到x++
实际上类似于operator++(operator++(x,int),int)
,所以现在发生的是第一个operator++
按值返回(这导致返回一个未命名的临时值)。这个未命名的临时值不能绑定到第二个(外部)的非常量引用参数调用,方法查找失败
最后请注意,您的实现实际上并没有实现后缀增量:它实现前缀增量或者修复实现以返回未修改的值。为什么这会让您感到惊讶?想想postfixoperator++
的语义,您返回什么,您尝试做什么,以及您尝试向谁做。为什么您的代码中需要friend
。@triclosan这里没有必要,但假设他有一个private成员并想要一个全局函数而不是成员重载?@triclosan,因为运算符++是一元函数,如果它是成员函数,它将只有一个参数(int)。我相信这个有两个参数的版本不是成员函数(即使它是在类中定义的)因此需要朋友。问题是后缀增量不能通过引用返回,因为它将返回已经增加的值!@MarkB:所以不能;我没有正确地阅读代码。他为什么要从operator++
afriend
开始?@NikBougalis:因为,当你不编写玩具类时作为演示,您可能希望数据成员是私有的。尽管它可以是成员,但如果您愿意的话。@NikBougalis:将其设置为非成员的一个很好的理由是,如果您编写x++++;
,您将得到错误而不是意外的结果,如问题所示。您可以只修改类类型的临时值/r值很好。问题是,如果按值返回,则无法链接运算符,因为运算符通过非常量引用获取第一个参数。@jrok(我实际上怀疑是这样的,但我不确定。)那么,如果我添加了“因此外部运算符+++
,它通过(非常量)获取,这是否正确引用,无法将其绑定到由值“”返回的对象上?那很好,我想。@jrok谢谢你的建议!现在,准备一些可怕的事情:!(当然没有用例,但仍然:/)PS:你收到我的了吗?我想给定你的代码,x++
实际上会编译,因为x.operator++(0)。operator++(0)
格式正确。您可以通过声明成员Number operator++(int)&
(但仅限于最近的gcc/clang版本)来解决此问题